def fix_double_nodes( coor, conns, eps ): n_nod, dim = coor.shape cmap = find_map( coor, nm.zeros( (0,dim) ), eps = eps, allow_double = True ) if cmap.size: print 'double nodes in input mesh!' print 'trying to fix...' while cmap.size: print cmap.size # Just like in Variable.equation_mapping()... ii = nm.argsort( cmap[:,1] ) scmap = cmap[ii] eq = nm.arange( n_nod ) eq[scmap[:,1]] = -1 eqi = eq[eq >= 0] eq[eqi] = nm.arange( eqi.shape[0] ) remap = eq.copy() remap[scmap[:,1]] = eq[scmap[:,0]] print coor.shape coor = coor[eqi] print coor.shape ccs = [] for conn in conns: ccs.append( remap[conn] ) conns = ccs cmap = find_map( coor, nm.zeros( (0,dim) ), eps = eps, allow_double = True ) print '...done' return coor, conns
def match_grid_plane( coor1, coor2, which ): """ Match coordinates `coor1` with `coor2` along the plane with normal axis `which`. """ from sfepy.fem.mesh import find_map if coor1.shape != coor2.shape: raise ValueError, 'incompatible shapes: %s == %s'\ % ( coor1.shape, coor2.shape) offset = coor1[0,which] - coor2[0,which] aux = coor2.copy() aux[:,which] += offset i1, i2 = find_map( coor1, aux, join = False ) if i1.shape[0] != coor1.shape[0]: print coor1[i1] print coor2[i2] print nm.abs(coor1[i1] - coor2[i2]).max(0) ii = nm.setdiff1d(nm.arange(coor1.shape[0]), i1) print coor1[ii] print coor2[ii] raise ValueError('cannot match nodes!') return i1, i2
def test(): x1 = nm.fix( nm.random.rand( 5, 3 ) * 5 ) / 10 x2 = nm.fix( nm.random.rand( 10, 3 ) * 5 ) / 10 cmap = find_map( x1, x2 ) conn1 = nm.array( [[range( 5 )], [range( 5 )]] ).squeeze() conn2 = nm.array( [[range( 10 )], [range( 10 )]] ).squeeze() conn2.shape = (4, 5) print x1 print conn1 print x2 print conn2 print cmap xx, conns = merge_mesh( x1, [conn1], x2, [conn2], cmap ) print xx print conns
def match_grid_plane(coor1, coor2, which): from sfepy.fem.mesh import find_map if coor1.shape != coor2.shape: raise ValueError, "incompatible shapes: %s == %s" % (coor1.shape, coor2.shape) offset = coor1[0, which] - coor2[0, which] aux = coor2.copy() aux[:, which] += offset i1, i2 = find_map(coor1, aux, join=False) if i1.shape[0] != coor1.shape[0]: print "cannot match nodes\n(%s,\n %s)" % (coor1[i1], coor2[i2]) print i1 print coor1 print i2 print coor2 raise ValueError return i1, i2
def match_coors(coors1, coors2): """ Match coordinates `coors1` with `coors2`. """ if coors1.shape != coors2.shape: raise ValueError('incompatible shapes: %s == %s' % (coors1.shape, coors2.shape)) i1, i2 = find_map(coors1, coors2, join=False) if i1.shape[0] != coors1.shape[0]: print coors1[i1] print coors2[i2] print nm.abs(coors1[i1] - coors2[i2]).max(0) ii = nm.setdiff1d(nm.arange(coors1.shape[0]), i1) print coors1[ii] print coors2[ii] raise ValueError('cannot match nodes!') return i1, i2
def match_grid_plane(coor1, coor2, which): """ Match coordinates `coor1` with `coor2` along the plane with normal axis `which`. """ if coor1.shape != coor2.shape: raise ValueError, 'incompatible shapes: %s == %s'\ % ( coor1.shape, coor2.shape) offset = coor1[0, which] - coor2[0, which] aux = coor2.copy() aux[:, which] += offset i1, i2 = find_map(coor1, aux, join=False) if i1.shape[0] != coor1.shape[0]: print coor1[i1] print coor2[i2] print nm.abs(coor1[i1] - coor2[i2]).max(0) ii = nm.setdiff1d(nm.arange(coor1.shape[0]), i1) print coor1[ii] print coor2[ii] raise ValueError('cannot match nodes!') return i1, i2
def compose_periodic_mesh(mesh_in, scale, repeat, eps, check_mvd=False): """ Create a new mesh from a periodic mesh by scaling it and repeating along each axis, Parameters ---------- mesh_in : Mesh instance The input periodic mesh. scale : float The scale parameter. repeat : array The number of repetitions of `mesh_in` along each axis. eps : float Tolerance for finding matching mesh vertices. check_mvd : bool If True, verify periodicity by checking approximate minimum vertex distance and minimum edge length. Returns ------- mesh_out : Mesh instance The composed periodic mesh. """ dim = mesh_in.dim bbox = mesh_in.get_bounding_box() mscale = bbox[1] - bbox[0] output('bbox:\n', bbox) centre0 = 0.5 * (bbox[1] + bbox[0]) output('centre:\n', centre0) scale = float(scale) if repeat is None: repeat = [scale] * dim repeat = nm.asarray(repeat) # Normalize original coordinates. coor0 = (mesh_in.coors - centre0) / (mscale) aux = fix_double_nodes(coor0, mesh_in.ngroups, mesh_in.conns, eps) coor0, ngroups0, mesh_in.conns = aux if check_mvd: mes0 = get_min_edge_size(coor0, mesh_in.conns) mvd0 = get_min_vertex_distance(coor0, mes0) if mes0 > (mvd0 + eps): output(' original min. "edge" length: %.5e' % mes0) output('original approx. min. vertex distance: %.5e' % mvd0) output('-> still double nodes in input mesh!') output('try increasing eps') raise ValueError('cannot fix double nodes!') output('composing periodic mesh...') for indx in cycle(repeat): aindx = nm.array(indx, dtype=nm.float64) centre = 0.5 * (2.0 * aindx - repeat + 1.0) output(indx, centre) if aindx.sum() == 0: coor = coor0 + centre ngroups = ngroups0 conns = mesh_in.conns else: coor1 = coor0 + centre ngroups1 = ngroups0 conns1 = mesh_in.conns cmap = find_map(coor, coor1, eps=eps) if not cmap.size: raise ValueError('non-periodic mesh!') else: output(cmap.size / 2) coor, ngroups, conns = merge_mesh(coor, ngroups, conns, coor1, ngroups1, conns1, cmap, eps=eps) if check_mvd: mes = get_min_edge_size( coor, conns ) mvd = get_min_vertex_distance( coor, mes0 ) output(' original min. "edge" length: %.5e' % mes0) output(' final min. "edge" length: %.5e' % mes) output('original approx. min. vertex distance: %.5e' % mvd0) output(' final approx. min. vertex distance: %.5e' % mvd) if mvd < 0.99999 * mvd0: if mvd0 < (mes0 - eps): output('-> probably non-periodic input mesh!') output(' - adjacent sides were not connected!') output(' try increasing eps') else: output('-> input mesh might be periodic') output(' try increasing eps') else: output('-> input mesh looks periodic') else: output('non-periodic input mesh detection skipped!') # Renormalize. coor = (coor * mscale) / scale mesh_out = make_mesh(coor, ngroups, conns, mesh_in) output('...done') return mesh_out
def main(): parser = OptionParser( usage = usage, version = "%prog 42" ) parser.add_option( "-s", "--scale", type = int, metavar = 'scale', action = "store", dest = "scale", default = 2, help = help['scale'] ) parser.add_option( "-e", "--eps", type = float, metavar = 'eps', action = "store", dest = "eps", default = 1e-8, help = help['eps'] ) parser.add_option( "-t", "--test", action = "store_true", dest = "test", default = False, help = help['test'] ) parser.add_option( "-n", "--no-mvd", action = "store_true", dest = "nomvd", default = False, help = help['nomvd'] ) (options, args) = parser.parse_args() if options.test: test() return if (len( args ) == 2): filename_in = args[0] filename_out = args[1] else: parser.print_help() return print 'scale:', options.scale print 'eps:', options.eps mesh_in = Mesh.from_file( filename_in ) bbox = mesh_in.get_bounding_box() print 'bbox:\n', bbox mscale = bbox[1] - bbox[0] centre0 = 0.5 * (bbox[1] + bbox[0]) print 'centre:\n', centre0 scale = nm.array( options.scale, dtype = nm.float64 ) # Normalize original coordinates. coor0 = (mesh_in.nod0[:,:-1] - centre0) / (mscale) dim = mesh_in.dim coor0, mesh_in.conns = fix_double_nodes( coor0, mesh_in.conns, options.eps ) if not options.nomvd: mes0 = get_min_edge_size( coor0, mesh_in.conns ) mvd0 = get_min_vertex_distance( coor0, mes0 ) if mes0 > (mvd0 + options.eps): print ' original min. "edge" length: %.5e' % mes0 print 'original approx. min. vertex distance: %.5e' % mvd0 print '-> still double nodes in input mesh!' print 'try increasing eps...' raise ValueError for indx in cycle( [options.scale] * dim ): aindx = nm.array( indx, dtype = nm.float64 ) centre = 0.5 * (2.0 * aindx - scale + 1.0) print indx, centre if aindx.sum() == 0: coor = coor0 + centre conns = mesh_in.conns else: coor1 = coor0 + centre conns1 = mesh_in.conns cmap = find_map( coor, coor1, eps = options.eps ) if not cmap.size: print 'non-periodic mesh!' # raise ValueError else: print cmap.size / 2 coor, conns = merge_mesh( coor, conns, coor1, conns1, cmap, eps = options.eps ) if not options.nomvd: mes = get_min_edge_size( coor, conns ) mvd = get_min_vertex_distance( coor, mes0 ) print ' original min. "edge" length: %.5e' % mes0 print ' final min. "edge" length: %.5e' % mes print 'original approx. min. vertex distance: %.5e' % mvd0 print ' final approx. min. vertex distance: %.5e' % mvd if mvd < 0.99999 * mvd0: if mvd0 < (mes0 - options.eps): print '-> probably non-periodic input mesh!' print ' ... adjacent sides were not connected!' print ' try increasing eps...' else: print '-> input mesh might be periodic' print ' try increasing eps...' else: print '-> input mesh looks periodic' else: print 'non-periodic input mesh detection skipped!' print 'renormalizing...' coor = (coor * mscale) / scale print 'saving...' mesh_out = make_mesh( coor, conns, mesh_in ) mesh_out.write( filename_out, io = 'auto' ) print 'done.'