def _make_iterator(repeat, n_row, n_col): ii = 0 for ij, iric in enumerate(cycle((n_row, n_col))): ir, ic = iric if ij < len(repeat): for ik in xrange(repeat[ij]): yield ii, ir, ic ii += 1
def make_axes(self): self.fig.clf() self.ax = [] n_col = min(5.0, nm.fix(nm.sqrt(self.n_gr))) if int(n_col) == 0: n_row = 0 else: n_row = int(nm.ceil(self.n_gr / n_col)) n_col = int(n_col) for ii, (ir, ic) in enumerate(cycle((n_col, n_row))): if ii == self.n_gr: break self.ax.append(self.fig.add_subplot(n_row, n_col, ii+1)) self.vlines.setdefault(ii, [])
def make_axes(self): self.fig.clf() self.ax = [] n_col = min(5.0, nm.fix(nm.sqrt(self.n_gr))) if int(n_col) == 0: n_row = 0 else: n_row = int(nm.ceil(self.n_gr / n_col)) n_col = int(n_col) for ii, (ir, ic) in enumerate(cycle((n_col, n_row))): if ii == self.n_gr: break self.ax.append(self.fig.add_subplot(n_row, n_col, ii + 1)) self.vlines.setdefault(ii, [])
def read_spline_box_hdf5(filename): if not pt.isHDF5File(filename): raise ValueError, 'not a HDF5 file! (%s)' % filename fd = pt.openFile(filename, mode='r') boxes = fd.listNodes('/box') n_box = len(boxes) dim = len(fd.listNodes(boxes[0].ax)) sp_boxes = SplineBoxes(dim=dim, n_box=n_box, n_vertex=0, spbs=OneTypeList(SplineBox)) for box in boxes: spb = SplineBox() sp_boxes.spbs.append(spb) spb.ib = int(box._v_name) spb.cpi = nm.asarray(box.cpi.read()) - 1 spb.gpi = nm.asarray(box.gpi.read()) - 1 spb.cxyz = nm.asarray(box.cxyz.read()).transpose() spb.cxyz0 = spb.cxyz.copy() spb.ax = [] for axi in fd.listNodes(box.ax): spb.ax.append(nm.asarray(axi.bsc.read())) sp_boxes.n_vertex = max(sp_boxes.n_vertex, nm.amax(spb.gpi) + 1) print nm.amin(spb.gpi), nm.amax(spb.gpi) ## # Fix cpi by rebuilding :). off = 0 n0, n1, n2 = spb.cpi.shape aux = nm.arange(n0 * n1).reshape(n1, n0).transpose() for ii in xrange(n2): spb.cpi[:, :, ii] = aux + off off += n0 * n1 fd.close() for perm in cycle([n_box] * 2): if perm[0] == perm[1]: continue gpi1 = sp_boxes.spbs[perm[0]].gpi gpi2 = sp_boxes.spbs[perm[1]].gpi assert_(len(nm.intersect1d(gpi1, gpi2)) == 0) return sp_boxes
def read_spline_box_hdf5( filename ): if not pt.isHDF5File( filename ): raise ValueError, 'not a HDF5 file! (%s)' % filename fd = pt.openFile( filename, mode = 'r' ) boxes = fd.listNodes( '/box' ) n_box = len( boxes ) dim = len( fd.listNodes( boxes[0].ax ) ) sp_boxes = SplineBoxes( dim = dim, n_box = n_box, n_vertex = 0, spbs = OneTypeList( SplineBox ) ) for box in boxes: spb = SplineBox() sp_boxes.spbs.append( spb ) spb.ib = int( box._v_name ) spb.cpi = nm.asarray( box.cpi.read() ) - 1 spb.gpi = nm.asarray( box.gpi.read() ) - 1 spb.cxyz = nm.asarray( box.cxyz.read() ).transpose() spb.cxyz0 = spb.cxyz.copy() spb.ax = [] for axi in fd.listNodes( box.ax ): spb.ax.append( nm.asarray( axi.bsc.read() ) ) sp_boxes.n_vertex = max( sp_boxes.n_vertex, nm.amax( spb.gpi ) + 1 ) print nm.amin( spb.gpi ), nm.amax( spb.gpi ) ## # Fix cpi by rebuilding :). off = 0 n0, n1, n2 = spb.cpi.shape aux = nm.arange( n0 * n1 ).reshape( n1, n0 ).transpose() for ii in xrange( n2 ): spb.cpi[:,:,ii] = aux + off off += n0 * n1 fd.close() for perm in cycle( [n_box] * 2 ): if perm[0] == perm[1]: continue gpi1 = sp_boxes.spbs[perm[0]].gpi gpi2 = sp_boxes.spbs[perm[1]].gpi assert_( len( nm.intersect1d( gpi1, gpi2 ) ) == 0 ) return sp_boxes
def __call__(self, u=None, v=None, w=None, field=None): """ Igakit-like interface for NURBS evaluation. """ pars = [u] if v is not None: pars += [v] if w is not None: pars += [w] indices = [] uks = [] rcs = [] for ia, par in enumerate(pars): uk, indx, rc = self._get_ref_coors_1d(par, ia) indices.append(indx) uks.append(uk) rcs.append(rc) shape = [len(ii) for ii in pars] n_vals = nm.prod(shape) if field is None: out = nm.zeros((n_vals, self.dim), dtype=nm.float64) else: out = nm.zeros((n_vals, field.shape[1]), dtype=nm.float64) for ip, igrid in enumerate(cycle(shape)): iis = [indices[ii][igrid[ii]] for ii in xrange(self.dim)] ie = iga.get_raveled_index(iis, self.n_els) rc = [rcs[ii][igrid[ii]] for ii in xrange(self.dim)] bf, bfg, det = iga.eval_nurbs_basis_tp(rc, ie, self.cps, self.weights, self.degrees, self.cs, self.conn) ec = self.conn[ie] if field is None: out[ip, :] = nm.dot(bf, self.cps[ec]) else: out[ip, :] = nm.dot(bf, field[ec]) return out
def main(): parser = OptionParser(usage=usage, version='%prog') parser.add_option('-b', '--basis', metavar='name', action='store', dest='basis', default='lagrange', help=help['basis']) parser.add_option('-d', '--derivative', metavar='d', type=int, action='store', dest='derivative', default=0, help=help['derivative']) parser.add_option('-n', '--max-order', metavar='order', type=int, action='store', dest='max_order', default=2, help=help['max_order']) parser.add_option('-g', '--geometry', metavar='name', action='store', dest='geometry', default='2_4', help=help['geometry']) parser.add_option('-m', '--mesh', metavar='mesh', action='store', dest='mesh', default=None, help=help['mesh']) parser.add_option('', '--permutations', metavar='permutations', action='store', dest='permutations', default=None, help=help['permutations']) parser.add_option('', '--dofs', metavar='dofs', action='store', dest='dofs', default=None, help=help['dofs']) parser.add_option('-l', '--lin-options', metavar='options', action='store', dest='lin_options', default='min_level=2,max_level=5,eps=1e-3', help=help['lin_options']) parser.add_option('', '--plot-dofs', action='store_true', dest='plot_dofs', default=False, help=help['plot_dofs']) options, args = parser.parse_args() if len(args) == 1: output_dir = args[0] else: parser.print_help(), return output('polynomial space:', options.basis) output('max. order:', options.max_order) lin = Struct(kind='adaptive', min_level=2, max_level=5, eps=1e-3) for opt in options.lin_options.split(','): key, val = opt.split('=') setattr(lin, key, eval(val)) if options.mesh is None: dim, n_ep = int(options.geometry[0]), int(options.geometry[2]) output('reference element geometry:') output(' dimension: %d, vertices: %d' % (dim, n_ep)) gel = GeometryElement(options.geometry) gps = PolySpace.any_from_args(None, gel, 1, base=options.basis) ps = PolySpace.any_from_args(None, gel, options.max_order, base=options.basis) n_digit, _format = get_print_info(ps.n_nod, fill='0') name_template = os.path.join(output_dir, 'bf_%s.vtk' % _format) for ip in get_dofs(options.dofs, ps.n_nod): output('shape function %d...' % ip) def eval_dofs(iels, rx): if options.derivative == 0: bf = ps.eval_base(rx).squeeze() rvals = bf[None, :, ip:ip+1] else: bfg = ps.eval_base(rx, diff=True) rvals = bfg[None, ..., ip] return rvals def eval_coors(iels, rx): bf = gps.eval_base(rx).squeeze() coors = nm.dot(bf, gel.coors)[None, ...] return coors (level, coors, conn, vdofs, mat_ids) = create_output(eval_dofs, eval_coors, 1, ps, min_level=lin.min_level, max_level=lin.max_level, eps=lin.eps) out = { 'bf' : Struct(name='output_data', mode='vertex', data=vdofs, var_name='bf', dofs=None) } mesh = Mesh.from_data('bf_mesh', coors, None, [conn], [mat_ids], [options.geometry]) name = name_template % ip ensure_path(name) mesh.write(name, out=out) output('...done (%s)' % name) else: mesh = Mesh.from_file(options.mesh) output('mesh geometry:') output(' dimension: %d, vertices: %d, elements: %d' % (mesh.dim, mesh.n_nod, mesh.n_el)) if options.permutations: if options.permutations == 'all': from sfepy.linalg import cycle gel = GeometryElement(mesh.descs[0]) n_perms = gel.get_conn_permutations().shape[0] all_permutations = [ii for ii in cycle(mesh.n_el * [n_perms])] else: all_permutations = [int(ii) for ii in options.permutations.split(',')] all_permutations = nm.array(all_permutations) np = len(all_permutations) all_permutations.shape = (np / mesh.n_el, mesh.n_el) output('using connectivity permutations:\n', all_permutations) else: all_permutations = [None] for ip, permutations in enumerate(all_permutations): if permutations is None: suffix = '' else: suffix = '_' + '_'.join('%d' % ii for ii in permutations) save_basis_on_mesh(mesh, options, output_dir, lin, permutations, suffix)
def gen_cylinder_mesh(dims, shape, centre, axis='x', force_hollow=False, is_open=False, open_angle=0.0, non_uniform=False, name='cylinder', verbose=True): """ Generate a cylindrical mesh along an axis. Its cross-section can be ellipsoidal. Parameters ---------- dims : array of 5 floats Dimensions of the cylinder: inner surface semi-axes a1, b1, outer surface semi-axes a2, b2, length. shape : array of 3 ints Shape (counts of nodes in radial, circumferential and longitudinal directions) of the cylinder mesh. centre : array of 3 floats Centre of the cylinder. axis: one of 'x', 'y', 'z' The axis of the cylinder. force_hollow : boolean Force hollow mesh even if inner radii a1 = b1 = 0. is_open : boolean Generate an open cylinder segment. open_angle : float Opening angle in radians. non_uniform : boolean If True, space the mesh nodes in radial direction so that the element volumes are (approximately) the same, making thus the elements towards the outer surface thinner. name : string Mesh name. verbose : bool If True, show progress of the mesh generation. Returns ------- mesh : Mesh instance """ dims = nm.asarray(dims, dtype=nm.float64) shape = nm.asarray(shape, dtype=nm.int32) centre = nm.asarray(centre, dtype=nm.float64) a1, b1, a2, b2, length = dims nr, nfi, nl = shape origin = centre - nm.array([0.5 * length, 0.0, 0.0]) dfi = 2.0 * (nm.pi - open_angle) / nfi if is_open: nnfi = nfi + 1 else: nnfi = nfi is_hollow = force_hollow or not (max(abs(a1), abs(b1)) < 1e-15) if is_hollow: mr = 0 else: mr = (nnfi - 1) * nl grid = nm.zeros((nr, nnfi, nl), dtype=nm.int32) n_nod = nr * nnfi * nl - mr coors = nm.zeros((n_nod, 3), dtype=nm.float64) angles = nm.linspace(open_angle, open_angle+(nfi)*dfi, nfi+1) xs = nm.linspace(0.0, length, nl) if non_uniform: ras = nm.zeros((nr,), dtype=nm.float64) rbs = nm.zeros_like(ras) advol = (a2**2 - a1**2) / (nr - 1) bdvol = (b2**2 - b1**2) / (nr - 1) ras[0], rbs[0] = a1, b1 for ii in range(1, nr): ras[ii] = nm.sqrt(advol + ras[ii-1]**2) rbs[ii] = nm.sqrt(bdvol + rbs[ii-1]**2) else: ras = nm.linspace(a1, a2, nr) rbs = nm.linspace(b1, b2, nr) # This is 3D only... output('generating %d vertices...' % n_nod, verbose=verbose) ii = 0 for ix in range(nr): a, b = ras[ix], rbs[ix] for iy, fi in enumerate(angles[:nnfi]): for iz, x in enumerate(xs): grid[ix,iy,iz] = ii coors[ii] = origin + [x, a * nm.cos(fi), b * nm.sin(fi)] ii += 1 if not is_hollow and (ix == 0): if iy > 0: grid[ix,iy,iz] = grid[ix,0,iz] ii -= 1 assert_(ii == n_nod) output('...done', verbose=verbose) n_el = (nr - 1) * nnfi * (nl - 1) conn = nm.zeros((n_el, 8), dtype=nm.int32) output('generating %d cells...' % n_el, verbose=verbose) ii = 0 for (ix, iy, iz) in cycle([nr-1, nnfi, nl-1]): if iy < (nnfi - 1): conn[ii,:] = [grid[ix ,iy ,iz ], grid[ix+1,iy ,iz ], grid[ix+1,iy+1,iz ], grid[ix ,iy+1,iz ], grid[ix ,iy ,iz+1], grid[ix+1,iy ,iz+1], grid[ix+1,iy+1,iz+1], grid[ix ,iy+1,iz+1]] ii += 1 elif not is_open: conn[ii,:] = [grid[ix ,iy ,iz ], grid[ix+1,iy ,iz ], grid[ix+1,0,iz ], grid[ix ,0,iz ], grid[ix ,iy ,iz+1], grid[ix+1,iy ,iz+1], grid[ix+1,0,iz+1], grid[ix ,0,iz+1]] ii += 1 mat_id = nm.zeros((n_el,), dtype = nm.int32) desc = '3_8' assert_(n_nod == (conn.max() + 1)) output('...done', verbose=verbose) if axis == 'z': coors = coors[:,[1,2,0]] elif axis == 'y': coors = coors[:,[2,0,1]] mesh = Mesh.from_data(name, coors, None, [conn], [mat_id], [desc]) return mesh
def gen_block_mesh(dims, shape, centre, name='block'): """ Generate a 2D or 3D block mesh. The dimension is determined by the lenght of the shape argument. Parameters ---------- dims : array of 2 or 3 floats Dimensions of the block. shape : array of 2 or 3 ints Shape (counts of nodes in x, y, z) of the block mesh. centre : array of 2 or 3 floats Centre of the block. name : string Mesh name. Returns ------- mesh : Mesh instance """ dims = nm.asarray(dims, dtype=nm.float64) shape = nm.asarray(shape, dtype=nm.int32) centre = nm.asarray(centre, dtype=nm.float64) dim = shape.shape[0] centre = centre[:dim] dims = dims[:dim] x0 = centre - 0.5 * dims dd = dims / (shape - 1) grid = nm.zeros(shape, dtype = nm.int32) n_nod = nm.prod(shape) coors = nm.zeros((n_nod, dim), dtype = nm.float64) bar = MyBar(" nodes:") bar.init(n_nod) for ii, ic in enumerate(cycle(shape)): grid[tuple(ic)] = ii coors[ii] = x0 + ic * dd if not (ii % 100): bar.update(ii) bar.update(ii + 1) n_el = nm.prod(shape - 1) mat_id = nm.zeros((n_el,), dtype = nm.int32) if (dim == 2): conn = nm.zeros((n_el, 4), dtype = nm.int32) bar = MyBar(" elements:") bar.init(n_el) for ii, (ix, iy) in enumerate(cycle(shape - 1)): conn[ii,:] = [grid[ix ,iy], grid[ix+1,iy ], grid[ix+1,iy+1], grid[ix ,iy+1]] if not (ii % 100): bar.update(ii) bar.update(ii + 1) desc = '2_4' else: conn = nm.zeros((n_el, 8), dtype = nm.int32) bar = MyBar(" elements:") bar.init(n_el) for ii, (ix, iy, iz) in enumerate(cycle(shape - 1)): conn[ii,:] = [grid[ix ,iy ,iz ], grid[ix+1,iy ,iz ], grid[ix+1,iy+1,iz ], grid[ix ,iy+1,iz ], grid[ix ,iy ,iz+1], grid[ix+1,iy ,iz+1], grid[ix+1,iy+1,iz+1], grid[ix ,iy+1,iz+1]] if not (ii % 100): bar.update(ii) bar.update(ii + 1) desc = '3_8' mesh = Mesh.from_data(name, coors, None, [conn], [mat_id], [desc]) return mesh
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.coors - centre0) / (mscale) dim = mesh_in.dim aux = fix_double_nodes(coor0, mesh_in.ngroups, mesh_in.conns, options.eps) coor0, ngroups0, mesh_in.conns = aux 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 ngroups = ngroups0 conns = mesh_in.conns else: coor1 = coor0 + centre ngroups1 = ngroups0 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, ngroups, conns = merge_mesh(coor, ngroups, conns, coor1, ngroups1, 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, ngroups, conns, mesh_in) mesh_out.write(filename_out, io="auto") print "done."