#!/usr/bin/ruby # Bjorn Bergqvist 20090324 # solved: replacement table for point numbers # find which bc that coincide # neighbour for merged bc line # assemble "mesh" # make "partial" merge possible (just delete coincided faces and points ) # methods def translate( x, y, movx, movy ) xres, yres = Array.new, Array.new x.each { |x| xres.push( x + movx ) } y.each { |y| yres.push( y + movy ) } return xres, yres end # cell definition [ p0, p1, p2, p3 ] def makecells( xysize, newcol ) startpoint = 0 newcellcol = newcol - 2 celldef = Array.new (0..xysize/newcol - 2).each do |col| (0..newcol - 2).each do |row| celldef.push( [row + (1+col)*newcol + startpoint, row + (1+col)*newcol + 1 + startpoint, row + col*newcol + 1 + startpoint, row + col*newcol + startpoint]) end end return celldef end def cellshift(celldef, startpoint) result = Array.new celldef.each { |cell| result.push( [ cell[0] + startpoint, cell[1] + startpoint, cell[2] + startpoint, cell[3] + startpoint ] ) } return result end # Mesh Export class class MeshExport # class variables @@celldef = Array.new @@pointx = Array.new @@pointy = Array.new @@ilines = Array.new @@owner = Array.new @@neighbour = Array.new @@bno = Array.new @@faceno = 0 def initialize end def add( celldef, newcol, pointx, pointy ) firstpoint = @@pointx.size @@celldef[ @@faceno ] = cellshift( celldef, firstpoint ) @@pointx += pointx @@pointy += pointy firstcell = 0 if @@neighbour.last != nil @@neighbour.last.flatten.each { |cell| firstcell = cell if ( cell > firstcell ) } firstcell += 1 end #puts "#{firstpoint} ####################################################################################################" @@ilines[ @@faceno], @@owner[ @@faceno ], @@neighbour[ @@faceno ], @@bno[ @@faceno ] = makelines( @@celldef[@@faceno], newcol, firstcell) @@faceno += 1 end # # bcranges calculates: # @xranges[ face number ][ bondary number ] # @yranges[ face number ][ bondary number ] # def bcranges @xranges = Array.new @yranges = Array.new (0..@@faceno - 1).each do |fno| @xranges[fno] = Array.new @yranges[fno] = Array.new (1..@@ilines[fno].size - 1).each do |bno| @xranges[fno][bno] = Array.new @yranges[fno][bno] = Array.new (0..@@ilines[fno][bno].size - 1).each do |lno| (0..@@ilines[fno][bno][lno].size - 1).each do |pno| #@xranges[fno][bno][pno] = pno pointno = @@ilines[fno][bno][lno][pno] #puts "faceno #{fno}, bcno #{bno}, pointno #{ pointno }, x #{@@pointx[pointno]}, y #{@@pointy[pointno]}" @xranges[fno][bno][pointno] = @@pointx[ pointno ] @yranges[fno][bno][pointno] = @@pointy[ pointno ] end end @xranges[fno][bno].compact! @yranges[fno][bno].compact! #puts "xranges #{@xranges[fno][bno].join(", ")}" #puts "yranges #{@yranges[fno][bno].join(", ")}" #puts "face no #{fno}, bondary no #{bno}, xmin #{@xranges[fno][bno].min}, xmax #{@xranges[fno][bno].max #}, ymin #{@yranges[fno][bno].min}, ymax #{@yranges[fno][bno].max}" end end end # see if ranges might coincide def testranges( x1, y1, x2, y2) tolerance = 1e-9 if x1.max + tolerance < x2.min return false end if y1.max + tolerance < y2.min return false end if x2.max + tolerance < x1.min return false end if y2.max + tolerance < y1.min return false end return true end def duplicatesubset( list1, list2) tolerance = 1e-9 keepidx = Array.new removeidx = Array.new list1.each do |p1| list2.each do |p2| if ( (@@pointx[p1] - @@pointx[p2]).abs < tolerance ) && ( (@@pointy[p1] - @@pointy[p2]).abs < tolerance ) keepidx.push( p1 ) removeidx.push( p2 ) end end end return removeidx, keepidx end def deletepoints @exportx, @exporty = @@pointx.clone, @@pointy.clone @delpoints.each { |delp| @exportx[delp], @exporty[delp] = nil, nil } @exportx.compact! @exporty.compact! end def replacetable # mergecandidates has to be run first @oldpointno = (0..@@pointx.size - 1).to_a puts "old index #{@oldpointno.join(", ")}" @newpointno = @oldpointno @delpoints.each_with_index do |delp, idx| (delp..@@pointx.size - 1).each do |del1| @newpointno[del1] -= 1 end end #@newpointno.compact! @delpoints.each_with_index do |delp, idx| @newpointno[delp] = @keeppoints[idx] end puts "new index #{@newpointno.join(", ")}" end def newno( oldno ) if oldno.class == Fixnum return @newpointno[oldno] elsif oldno.class == Array if oldno[0].class == Array result = Array.new oldno.each_with_index do |olda,idx| result[idx] = Array.new olda.each { |oldp| result[idx].push( newno(oldp) ) } end return result else result = Array.new oldno.each { |oldp| result.push( newno(oldp) ) } return result end end end # find out which faces that might coincide def mergecandidates bcranges @delpoints = Array.new @keeppoints = Array.new @removebc = Array.new @internalbc = Array.new @checkbc = Array.new (0..@@faceno - 2).each do |face1| (face1 + 1..@@faceno - 1).each do |face2| # puts "face1 #{face1}, face2 #{face2}" (1..4).each do |b1| (1..4).each do |b2| coincide = testranges( @xranges[face1][b1], @yranges[face1][b1], @xranges[face2][b2], @yranges[face2][b2] ) # puts "compare face #{face1}, bno #{b1} with face #{face2}, bno #{b2} result #{coincide}" if coincide if coincide remove, keep = duplicatesubset( @@ilines[face1][b1].flatten.uniq, @@ilines[face2][b2].flatten.uniq ) #puts "keep #{keep.join(", ")}, remove #{remove.join(", ")}" @delpoints.push(remove) @keeppoints.push(keep) # remove bc if more than 1 point is duplicate if remove.size > 1 @internalbc.push( [ face1, b1 ] ) @removebc.push( [ face2, b2 ] ) # check bc if one point is duplicate else @checkbc.push( [ face2, b2 ] ) end puts "delete boundary face#{face2} bno #{b2}" if remove.size > 1 end end end end end @delpoints.flatten! @delpoints.uniq! @keeppoints.flatten! @keeppoints.uniq! puts "delete points \t#{@delpoints.join(", ")}" puts "keep points \t#{@keeppoints.join(", ")}" @removebc.each do |rbc| puts "remove bc #{rbc[1]} of face #{rbc[0]}" end @checkbc.each do |rbc| puts "check bc #{rbc[1]} of face #{rbc[0]}" end end def createneighbour @removeafter = Array.new (0..@internalbc.size - 1).each do |line| puts "neighbour for face #{@internalbc[line][0]} line #{@internalbc[line][1]} remove face #{@removebc[line][0]} line #{@removebc[line][1]}" internal = @internalbc[line] remove = @removebc[line] intface, intline = internal[0], internal[1] remface, remline = remove[0], remove[1] # puts "lines with neighbour #{@@ilines[intface][intline].join(", ")}" @@ilines[intface][intline].each_with_index do |line1,idx1| @@ilines[remface][remline].each_with_index do |line2,idx2| if line1.sort == newno(line2).sort # puts "line1 #{line1.join(", ")}, idx1 #{idx1}, line2 #{line2.join(", ")}, idx2 #{idx2}" # puts "2line1 #{line1.join(", ")}, idx1 #{idx1}, line2 #{newno(line2).join(", ")}, idx2 #{idx2}" @@ilines[intface][5].push( @@ilines[intface][intline][idx1] ) @@neighbour[intface][5].push( @@owner[remface][remline][idx2] ) @@owner[intface][5].push( @@owner[intface][intline][idx1] ) @@bno[intface][5].push( @@bno[intface][intline][idx1] ) # @@bno[intface][0].push( -1 ) give new boundary idx? @removeafter.push( [intface, intline, idx1] ) @removeafter.push( [remface, remline, idx2] ) end end end end #@removeafter.each { |rem| @@ilines[ rem[0] ][ rem[1] ][ rem[2] ] = nil } #@removeafter.each { |rem| @@neighbour[ rem[0] ][ rem[1] ][ rem[2] ] = nil } #@removeafter.each { |rem| @@owner[ rem[0] ][ rem[1] ][ rem[2] ] = nil } #@removeafter.each { |rem| @@bno[ rem[0] ][ rem[1] ][ rem[2] ] = nil } end def deletebc createneighbour =begin @removebc.each do |delbc| @@ilines[ delbc[0] ][ delbc[1] ] = nil @@owner[ delbc[0] ][ delbc[1] ] = nil @@neighbour[ delbc[0] ][ delbc[1] ] = nil @@bno[ delbc[0] ][ delbc[1] ] = nil end @internalbc.each do |intbc| @@owner[ intbc[0] ][ 0 ] += @@owner[ intbc[0] ][ intbc[1] ] @@owner[ intbc[0] ][ intbc[1] ] = nil @@neighbour[ intbc[0] ][ 0 ] += @@neighbour[ intbc[0] ][ intbc[1] ] @@neighbour[ intbc[0] ][ intbc[1] ] = nil @@ilines[ intbc[0] ][ 0 ] += @@ilines[ intbc[0] ][ intbc[1] ] @@ilines[ intbc[0] ][ intbc[1] ] = nil end =end end def print (0..@@ilines.size - 1).each do |idx| puts "\nface #{idx}" printlines( @@ilines[ idx ] , @@owner[ idx ], @@neighbour[ idx], @@bno[ idx ] ) end puts "\npoints" puts @@pointx.join(", ") puts @@pointy.join(", ") end def merge removep, keepp = duplicatepoints( @@pointx, @@pointy ) puts "duplicate points, remove #{removep.join(", ")}" puts "duplicate points, keep #{keepp.join(", ")}" end def export (0..@@ilines.size - 1).each { |faceno| @@ilines[faceno][5] = Array.new } (0..@@neighbour.size - 1).each { |faceno| @@neighbour[faceno][5] = Array.new } (0..@@owner.size - 1).each { |faceno| @@owner[faceno][5] = Array.new } (0..@@bno.size - 1).each { |faceno| @@bno[faceno][5] = Array.new } mergecandidates replacetable deletepoints createneighbour pointsfile = File.open( "points", "w" ) pointxy = Array.new (0..@exportx.size - 1).each do |pidx| pointxy.push( "#{@exportx[pidx]} #{@exporty[pidx]}") #pointxy.push( "#{pidx} #{@@pointx[pidx]} #{@@pointy[pidx]}") end pointsfile.write( pointxy.join("\n") + "\n" ) pointsfile.close puts "points file written" ownerfile = File.open( "owner", "w" ) ownerarray = Array.new @@owner.each { |face| ownerarray.push( face[0] ) } @@owner.each { |face| ownerarray.push( face[5] ) if face[5].size > 0 } #@@owner.each { |face| face[1..4].flatten.each { |bc| ownerarray.push( bc ) if bc != nil } } @@owner.each_with_index do |face,fidx| (1..4).each do |bc| face[bc].each_with_index do |bcline,bidx| if !@removeafter.member?( [fidx, bc, bidx] ) ownerarray.push( bcline ) #puts "a member #{@@owner[fidx][bc][bidx]}" end end end end #@@owner.each { |face| face[0..4].flatten.each { |bc| puts "1 #{bc}"} } #@@owner.each do |face| # (1..4).each do |bcno| # puts "2 #{face[bcno].join(", ")}" if face[bcno].class == Array # end #end ownerfile.write( ownerarray.compact.join("\n") + "\n" ) ownerfile.close puts "owner file written" neighbourfile = File.open( "neighbour", "w" ) neighbourarray = Array.new @@neighbour.each { |face| neighbourarray.push( face[0] ) } @@neighbour.each { |face| neighbourarray.push( face[5] ) if face[5].size > 0 } #@@neighbour.each { |face| face[1..4].flatten.each { |bc| neighbourarray.push( bc ) if bc !=nil } } @@neighbour.each_with_index do |face,fidx| (1..4).each do |bc| face[bc].each_with_index do |bcline,bidx| if !@removeafter.member?( [fidx, bc, bidx] ) neighbourarray.push( bcline ) && bcline != nil #puts "a member #{@@neighbour[fidx][bc][bidx]}" end end end end neighbourfile.write( neighbourarray.compact.join("\n") + "\n" ) neighbourfile.close puts "neighbour file written" bnofile = File.open( "bno", "w" ) bnoarray = Array.new @@bno.each { |face| bnoarray.push( face[0] ) } @@bno.each { |face| bnoarray.push( face[5] ) if face[5].size > 0 } #@@bno.each { |face| face[1..4].flatten.each { |bc| bnoarray.push( bc ) if bc != nil } } @@bno.each_with_index do |face,fidx| (1..4).each do |bc| face[bc].each_with_index do |bcline,bidx| if !@removeafter.member?( [fidx, bc, bidx] ) && bcline != nil bnoarray.push( bcline ) end end end end bnofile.write( bnoarray.compact.join("\n") + "\n" ) bnofile.close puts "bno file written" linesfile = File.open( "lines", "w" ) linesarray = Array.new @@ilines.each { |face| face[0].each { |line| linesarray.push(newno(line).join(" ")) } } @@ilines.each { |face| face[5].each { |line| linesarray.push(newno(line).join(" ")) } } #@@ilines.each { |lines| [lines[1], lines[2],lines[3], lines[4]].each { |line| linesarray.push( line.join(" ")) if line.class == Array } } #@@ilines.each { |lines| lines[1..4].each { |line| } } @@ilines.each_with_index do |face,fidx| (1..4).each do |bno| (0..face[bno].size - 1).each do |lineidx| linesarray.push( newno(face[bno][lineidx]).join(" ") ) if !@removeafter.member?([fidx,bno,lineidx]) if face[bno][lineidx] != nil end end end linesfile.write( linesarray.compact.join("\n") + "\n" ) linesfile.close puts "lines file written" end end # line definition xi = internal line in xdir, yi = internal line in ydir, xmin, xmax, ymin, ymax = boundary lines def makelines( celldef, newcol, startcell ) #ymin ymin = ( 0.. newcol - 1 ).to_a #ymax ymax = ( celldef.size - newcol..celldef.size - 1 ).to_a xmin, xmax = Array.new, Array.new # xmin (0..celldef.size - 1).each { |cellno| xmin.push( cellno ) if cellno%newcol == 0 } # xmax (0..celldef.size - 1).each { |cellno| xmax.push( cellno ) if ( (cellno + 1)%newcol == 0 && cellno != 0 ) || (newcol == 1 && cellno == 0 ) } ilines = Array.new owner, neighbour = Array.new, Array.new # bno, boundary number. Internal -1, negx 0, posx 1, negy 2, posy 3 bno = Array.new # 5 groups of bc: internal and 4 edge lines (0..4).each { |idx| ilines[idx], owner[idx], neighbour[idx], bno[idx] = Array.new, Array.new, Array.new, Array.new } (0..celldef.size - 1).each do |cellno| # x direction if !xmax.member?cellno ilines[0].push( [ celldef[cellno][1], celldef[cellno][2] ] ) owner[0].push( cellno + startcell ) neighbour[0].push( cellno + 1 + startcell ) bno[0].push( -1 ) end # y direction if !ymax.member?cellno ilines[0].push( [ celldef[cellno][0], celldef[cellno][1] ] ) owner[0].push( cellno + startcell ) neighbour[0].push( cellno + newcol + startcell ) bno[0].push( -1 ) end end # bondary lines # outer lines xmin.each do |cellno| ilines[1].push( [ celldef[cellno][3], celldef[cellno][0] ] ) owner[1].push( cellno + startcell ) neighbour[1].push( -1 ) bno[1].push( 0 ) end xmax.each do |cellno| ilines[2].push( [ celldef[cellno][1], celldef[cellno][2] ] ) owner[2].push( cellno + startcell ) neighbour[2].push( -1 ) bno[2].push( 1 ) end ymin.each do |cellno| ilines[3].push( [ celldef[cellno][2], celldef[cellno][3] ] ) owner[3].push( cellno + startcell ) neighbour[3].push( -1 ) bno[3].push( 2 ) end ymax.each do |cellno| ilines[4].push( [ celldef[cellno][0], celldef[cellno][1] ] ) owner[4].push( cellno + startcell ) neighbour[4].push( -1 ) bno[4].push( 3 ) end return ilines, owner, neighbour, bno end # find duplicate points and return index of the duplicate points def duplicatepoints( px, py ) tolerance = 1e-9 maxidx = [ px.size, py.size ].min - 1 keepidx = Array.new removeidx = Array.new (0..maxidx).each do |idx1| (idx1 + 1..maxidx).each do |idx2| #if px[idx1] == px[idx2] && py[idx1] == py[idx2] if ( (px[idx1] - px[idx2]).abs < tolerance ) && ( (py[idx1] - py[idx2]).abs < tolerance ) # puts "idx1 #{idx1}, idx2 #{idx2}, px[idx1] #{px[idx1]}, py[idx1] #{py[idx1]}, px[idx2] #{px[idx2]}, py[idy2] #{py[idx2]}" keepidx.push( idx1 ) removeidx.push( idx2 ) end end end return removeidx, keepidx end def printlines( ilines, owner, neighbour, bno) (0..4).each do |idx| puts "owner#{idx} #{owner[idx].join(", ")}" if owner[idx] != nil puts "neighbour#{idx} #{neighbour[idx].join(", ")}" if neighbour[idx] != nil puts "bno#{idx} #{bno[idx].join(", ")}" if bno[idx] != nil #puts "lines #{ilines.join(", ")}" string = "lines#{idx} " ilines[idx].each { |face| string += "[#{face.join(",")}] " if face != nil } if ilines[idx] != nil string += "\n" puts string end end def printcells(celldef, newrow ) puts "cell printout, size #{celldef.size}" celldef.each_with_index do |cell, idx| print "[ #{cell[0]}, #{cell[1]}, #{cell[2]}, #{cell[3]} ], " print "\n" if (idx+1.0)%newrow.to_f == 0.0 end print "\n" end # # example usage # # face 1 # 24 points, breakpoint 3 celldef1 = makecells( 24, 3 ) f1x = [ 0.0, 1.0, 2.0, 0.0, 1.0, 2.0, 0.0, 1.0, 2.0 ,0.0, 1.0, 2.0 ,0.0, 1.0, 2.0, 0.0, 1.0, 2.0, 0.0, 1.0, 2.0, 0.0, 1.0, 2.0 ] f1y = [ 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 5.0, 5.0, 5.0, 6.0, 6.0, 6.0, 7.0, 7.0, 7.0 ] # face 2 # 6 points, breakpoint 3 celldef2 = makecells( 6, 3 ) f2x = [ 2.0, 3.0, 4.0, 2.0, 3.0, 4.0 ] f2y = [ 0.0, 0.0, 0.0, 1.0, 1.0, 1.0 ] celldef3 = makecells( 6, 3 ) f3x, f3y = translate( f2x, f2y, 0.0, 3.0 ) # possible usage of export class export = MeshExport.new # breakcell 2 = breakpoint 3: point1 -- cell1 -- point2 -- cell2 -- point3 export.add( celldef1, 2, f1x, f1y) export.add( celldef2, 2, f2x, f2y) export.add( celldef3, 2, f3x, f3y) export.export