def from_conf(conf, dpb, apb): opts = conf.options regions = dpb.domain.regions if opts.use_mesh_velocity: import tables as pt fd = pt.open_file(opts.mesh_velocity_filename, mode='r') aux = fd.get_node('/u').read() nu = nm.asarray(aux, dtype=nm.float64) fd.close() else: nu = None sp_boxes = ffd.read_spline_box_hdf5(opts.ffd_spline_data) dsg_vars = ffd.read_dsg_vars_hdf5(opts.ffd_spline_data) dsg_vars.renumber_by_boxes(sp_boxes) dsg_vars.normalize_null_space_base() print dsg_vars.indx.shape print dsg_vars.null_space_b.shape control_region = regions[opts.control_domain] design_region = regions[opts.design_domain] from sfepy.discrete.fem.mesh import Mesh cmm = Mesh.from_region(control_region, dpb.domain.mesh) dmm = Mesh.from_region(design_region, dpb.domain.mesh) cmm.write('control.mesh', io='auto') dmm.write('design.mesh', io='auto') SOFC = ShapeOptimFlowCase obj = SOFC(dpb=dpb, apb=apb, sp_boxes=sp_boxes, dsg_vars=dsg_vars, problem_type=opts.problem, objective_function_type=opts.objective_function, var_map=opts.var_map, nu=nu, use_mesh_velocity=opts.use_mesh_velocity, save_dir=opts.save_dir, save_iter_sols=opts.save_iter_sols, save_control_points=opts.save_control_points, save_dsg_vars=opts.save_dsg_vars, test_terms_if_test=opts.test_terms_if_test) equations = getattr( conf, '_'.join(('equations_sensitivity', opts.problem, opts.objective_function))) obj.obj_fun_term = equations['objective'] obj.sens_terms = equations['sensitivity'] obj.n_var = dsg_vars.val.shape[0] obj.create_evaluables() return obj
def from_conf(conf, dpb, apb): opts = conf.options regions = dpb.domain.regions if opts.use_mesh_velocity: import tables as pt fd = pt.open_file( opts.mesh_velocity_filename, mode = 'r' ) aux = fd.get_node( '/u' ).read() nu = nm.asarray( aux, dtype = nm.float64 ) fd.close() else: nu = None sp_boxes = ffd.read_spline_box_hdf5( opts.ffd_spline_data ) dsg_vars = ffd.read_dsg_vars_hdf5( opts.ffd_spline_data ) dsg_vars.renumber_by_boxes( sp_boxes ) dsg_vars.normalize_null_space_base() print dsg_vars.indx.shape print dsg_vars.null_space_b.shape control_region = regions[opts.control_domain] design_region = regions[opts.design_domain] from sfepy.discrete.fem.mesh import Mesh cmm = Mesh.from_region(control_region, dpb.domain.mesh) dmm = Mesh.from_region(design_region, dpb.domain.mesh) cmm.write( 'control.mesh', io = 'auto' ) dmm.write( 'design.mesh', io = 'auto' ) SOFC = ShapeOptimFlowCase obj = SOFC(dpb=dpb, apb=apb, sp_boxes=sp_boxes, dsg_vars=dsg_vars, problem_type=opts.problem, objective_function_type=opts.objective_function, var_map=opts.var_map, nu=nu, use_mesh_velocity=opts.use_mesh_velocity, save_dir=opts.save_dir, save_iter_sols=opts.save_iter_sols, save_control_points=opts.save_control_points, save_dsg_vars=opts.save_dsg_vars, test_terms_if_test=opts.test_terms_if_test) equations = getattr( conf, '_'.join( ('equations_sensitivity', opts.problem, opts.objective_function) ) ) obj.obj_fun_term = equations['objective'] obj.sens_terms = equations['sensitivity'] obj.n_var = dsg_vars.val.shape[0] obj.create_evaluables() return obj
def gen_mesh_from_geom(geo, a=None, verbose=False, refine=False): """ Runs mesh generator - tetgen for 3D or triangle for 2D meshes. Parameters ---------- geo : geometry geometry description a : int, optional a maximum area/volume constraint verbose : bool, optional detailed information refine : bool, optional refines mesh Returns ------- mesh : Mesh instance triangular or tetrahedral mesh """ import os.path as op import pexpect import tempfile import shutil tmp_dir = tempfile.mkdtemp() polyfilename = op.join(tmp_dir, 'meshgen.poly') # write geometry to poly file geo.to_poly_file(polyfilename) meshgen_call = {2: ('triangle', ''), 3: ('tetgen', 'BFENk')} params = "-ACp" params += "q" if refine else '' params += "V" if verbose else "Q" params += meshgen_call[geo.dim][1] if a is not None: params += "a%f" % (a) params += " %s" % (polyfilename) cmd = "%s %s" % (meshgen_call[geo.dim][0], params) if verbose: print "Generating mesh using", cmd p=pexpect.run(cmd, timeout=None) bname, ext = op.splitext(polyfilename) if geo.dim == 2: mesh = Mesh.from_file(bname + '.1.node') if geo.dim == 3: mesh = Mesh.from_file(bname + '.1.vtk') shutil.rmtree(tmp_dir) return mesh
def create_mesh(self, extra_nodes=True): """ Create a mesh from the field region, optionally including the field extra nodes. """ mesh = self.domain.mesh if self.approx_order != 0: conns, mat_ids, descs = [], [], [] for ig, ap in self.aps.iteritems(): group = self.domain.groups[ig] if extra_nodes: conn = ap.econn else: offset = group.shape.n_ep conn = ap.econn[:,:offset] conns.append(conn) mat_ids.append(mesh.mat_ids[ig]) descs.append(mesh.descs[ig]) if extra_nodes: coors = self.coors else: coors = self.coors[:self.n_vertex_dof] mesh = Mesh.from_data(self.name, coors, None, conns, mat_ids, descs) return mesh
def create_mesh(self, extra_nodes=True): """ Create a mesh from the field region, optionally including the field extra nodes. """ mesh = self.domain.mesh if self.approx_order != 0: if extra_nodes: conn = self.econn else: conn = self.econn[:, :self.gel.n_vertex] conns = [conn] mat_ids = [mesh.cmesh.cell_groups] descs = mesh.descs[:1] if extra_nodes: coors = self.coors else: coors = self.coors[:self.n_vertex_dof] mesh = Mesh.from_data(self.name, coors, None, conns, mat_ids, descs) return mesh
def main(): parser = ArgumentParser(description=__doc__) parser.add_argument("--version", action="version", version="%(prog)s 42") parser.add_argument("-s", "--scale", type=int, metavar='scale', action="store", dest="scale", default=2, help=helps['scale']) parser.add_argument("-r", "--repeat", type=str, metavar='nx,ny[,nz]', action=ParseRepeat, dest="repeat", default=None, help=helps['repeat']) parser.add_argument("-e", "--eps", type=float, metavar='eps', action="store", dest="eps", default=1e-8, help=helps['eps']) parser.add_argument('filename_in') parser.add_argument('filename_out') options = parser.parse_args() filename_in = options.filename_in filename_out = options.filename_out output = Output('tpm:') output('scale:', options.scale) output('repeat:', options.repeat) output('eps:', options.eps) mesh_in = Mesh.from_file(filename_in) mesh_out = gen_tiled_mesh(mesh_in, options.repeat, 1./options.scale, options.eps) mesh_out.write(filename_out, io='auto') output('done.')
def load_state_1D_vtk(name): """Load one VTK file containing state in time Parameters ---------- name : str Returns ------- coors : ndarray u : ndarray """ from sfepy.discrete.fem.meshio import MeshioLibIO io = MeshioLibIO(name) coors = io.read(Mesh()).coors[:, 0, None] data = io.read_data(step=0) var_name = head([k for k in data.keys() if "_modal" in k])[:-1] if var_name is None: print("File {} does not contain modal data.".format(name)) return porder = len([k for k in data.keys() if var_name in k]) u = nm.zeros((porder, coors.shape[0] - 1, 1, 1)) for ii in range(porder): u[ii, :, 0, 0] = data[var_name+'{}'.format(ii)].data return coors, u
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("-r", "--repeat", type='str', metavar='nx,ny[,nz]', action="callback", dest="repeat", callback=parse_repeat, default=None, help=help['repeat']) parser.add_option("-e", "--eps", type=float, metavar='eps', action="store", dest="eps", default=1e-8, help=help['eps']) (options, args) = parser.parse_args() if (len( args ) == 2): filename_in = args[0] filename_out = args[1] else: parser.print_help() return output = Output('tpm:') output('scale:', options.scale) output('repeat:', options.repeat) output('eps:', options.eps) mesh_in = Mesh.from_file(filename_in) mesh_out = gen_tiled_mesh(mesh_in, options.repeat, 1./options.scale, options.eps) mesh_out.write(filename_out, io='auto') output('done.')
def linearize(self, dofs, min_level=0, max_level=1, eps=1e-4): """ Linearize the solution for post-processing. Parameters ---------- dofs : array, shape (n_nod, n_component) The array of DOFs reshaped so that each column corresponds to one component. min_level : int The minimum required level of mesh refinement. max_level : int The maximum level of mesh refinement. eps : float The relative tolerance parameter of mesh adaptivity. Returns ------- mesh : Mesh instance The adapted, nonconforming, mesh. vdofs : array The DOFs defined in vertices of `mesh`. levels : array of ints The refinement level used for each element group. """ assert_(dofs.ndim == 2) n_nod, dpn = dofs.shape assert_(n_nod == self.n_nod) assert_(dpn == self.shape[0]) vertex_coors = self.coors[:self.n_vertex_dof, :] ap = self.ap ps = ap.interp.poly_spaces['v'] gps = ap.interp.gel.interp.poly_spaces['v'] vertex_conn = ap.econn[:, :self.gel.n_vertex] eval_dofs = get_eval_dofs(dofs, ap.econn, ps, ori=ap.ori) eval_coors = get_eval_coors(vertex_coors, vertex_conn, gps) (level, coors, conn, vdofs, mat_ids) = create_output(eval_dofs, eval_coors, vertex_conn.shape[0], ps, min_level=min_level, max_level=max_level, eps=eps) mesh = Mesh.from_data('linearized_mesh', coors, None, [conn], [mat_ids], self.domain.mesh.descs) return mesh, vdofs, level
def gen_block_mesh(dims, shape, centre, mat_id=0, name='block', coors=None, verbose=True): """ 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. mat_id : int, optional The material id of all elements. 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) dim = shape.shape[0] centre = centre[:dim] dims = dims[:dim] n_nod = nm.prod(shape) output('generating %d vertices...' % n_nod, verbose=verbose) x0 = centre - 0.5 * dims dd = dims / (shape - 1) ngrid = nm.mgrid[[slice(ii) for ii in shape]] ngrid.shape = (dim, n_nod) coors = x0 + ngrid.T * dd output('...done', verbose=verbose) n_el = nm.prod(shape - 1) output('generating %d cells...' % n_el, verbose=verbose) mat_ids = nm.empty((n_el,), dtype=nm.int32) mat_ids.fill(mat_id) conn, desc = get_tensor_product_conn(shape) output('...done', verbose=verbose) mesh = Mesh.from_data(name, coors, None, [conn], [mat_ids], [desc]) return mesh
def test_mesh_expand(self): import numpy as nm from sfepy.mesh.mesh_tools import expand2d from sfepy.discrete.fem.mesh import Mesh from sfepy import data_dir mesh2d = Mesh.from_file(data_dir + '/meshes/2d/square_quad.mesh') mesh3d_ref = Mesh.from_file(data_dir +\ '/meshes/3d/cube_medium_hexa.mesh') mesh3d_gen = expand2d(mesh2d, 0.1, 10) mesh3d_gen.coors[:,2] += -0.5 d0 = nm.sort(nm.linalg.norm(mesh3d_ref.coors, axis=1)) d1 = nm.sort(nm.linalg.norm(mesh3d_gen.coors, axis=1)) if nm.linalg.norm(d0 - d1) < 1e-6: return True else: return False return True
def test_mesh_expand(self): import numpy as nm from sfepy.mesh.mesh_tools import expand2d from sfepy.discrete.fem.mesh import Mesh from sfepy import data_dir mesh2d = Mesh.from_file(data_dir + '/meshes/2d/square_quad.mesh') mesh3d_ref = Mesh.from_file(data_dir +\ '/meshes/3d/cube_medium_hexa.mesh') mesh3d_gen = expand2d(mesh2d, 0.1, 10) mesh3d_gen.coors[:, 2] += -0.5 d0 = nm.sort(nm.linalg.norm(mesh3d_ref.coors, axis=1)) d1 = nm.sort(nm.linalg.norm(mesh3d_gen.coors, axis=1)) if nm.linalg.norm(d0 - d1) < 1e-6: return True else: return False return True
def main(): parser = ArgumentParser(description=__doc__) parser.add_argument("--version", action="version", version="%(prog)s 42") parser.add_argument("-s", "--scale", type=int, metavar='scale', action="store", dest="scale", default=2, help=help['scale']) parser.add_argument("-r", "--repeat", type=str, metavar='nx,ny[,nz]', action=ParseRepeat, dest="repeat", default=None, help=help['repeat']) parser.add_argument("-e", "--eps", type=float, metavar='eps', action="store", dest="eps", default=1e-8, help=help['eps']) parser.add_argument('filename_in') parser.add_argument('filename_out') options = parser.parse_args() filename_in = options.filename_in filename_out = options.filename_out output = Output('tpm:') output('scale:', options.scale) output('repeat:', options.repeat) output('eps:', options.eps) mesh_in = Mesh.from_file(filename_in) mesh_out = gen_tiled_mesh(mesh_in, options.repeat, 1. / options.scale, options.eps) mesh_out.write(filename_out, io='auto') output('done.')
def test_mesh_smoothing(self): from sfepy.mesh.mesh_tools import smooth_mesh from sfepy.discrete.fem.mesh import Mesh from sfepy import data_dir mesh = Mesh.from_file(data_dir + '/meshes/3d/cylinder.vtk') vol0 = get_volume(mesh.conns[0], mesh.coors) mesh.coors = smooth_mesh(mesh, n_iter=10) vol1 = get_volume(mesh.conns[0], mesh.coors) filename = op.join(self.options.out_dir, 'smoothed_cylinder.vtk') mesh.write(filename) frac = vol1 / vol0 if (frac < 0.967) and (frac > 0.966): self.report('mesh smoothed') return True else: self.report('mesh smoothed, volume mismatch!') return False
def from_conf(conf, init_fields=True, init_equations=True, init_solvers=True): if conf.options.get('absolute_mesh_path', False): conf_dir = None else: conf_dir = op.dirname(conf.funmod.__file__) functions = Functions.from_conf(conf.functions) if conf.get('filename_mesh') is not None: from sfepy.discrete.fem.domain import FEDomain mesh = Mesh.from_file(conf.filename_mesh, prefix_dir=conf_dir) domain = FEDomain(mesh.name, mesh) if conf.options.get('ulf', False): domain.mesh.coors_act = domain.mesh.coors.copy() elif conf.get('filename_domain') is not None: from sfepy.discrete.iga.domain import IGDomain domain = IGDomain.from_file(conf.filename_domain) else: raise ValueError('missing filename_mesh or filename_domain!') obj = Problem('problem_from_conf', conf=conf, functions=functions, domain=domain, auto_conf=False, auto_solvers=False) obj.set_regions(conf.regions, obj.functions) obj.clear_equations() if init_fields: obj.set_fields(conf.fields) if init_equations: obj.set_equations(conf.equations, user={'ts' : obj.ts}) if init_solvers: obj.set_solvers(conf.solvers, conf.options) return obj
def create_mesh_from_control_points(self): offset = 0 dim = self.spbs[0].cxyz.shape[1] coors = nm.empty((0, dim), dtype=nm.float64) conns = [] mat_ids = [] descs = [] for ib, spb in enumerate(self.spbs): n_nod = spb.cxyz.shape[0] coors = nm.concatenate((coors, spb.cxyz), 0) descs.append('3_2') conn = [] for ij in xrange(spb.cpi.shape[1]): for ik in xrange(spb.cpi.shape[2]): inx = spb.cpi[:, ij, ik] row = [[p1, p2] for p1, p2 in zip(inx[:-1], inx[1:])] conn.extend(row) for ij in xrange(spb.cpi.shape[0]): for ik in xrange(spb.cpi.shape[2]): inx = spb.cpi[ij, :, ik] row = [[p1, p2] for p1, p2 in zip(inx[:-1], inx[1:])] conn.extend(row) for ij in xrange(spb.cpi.shape[0]): for ik in xrange(spb.cpi.shape[1]): inx = spb.cpi[ij, ik, :] row = [[p1, p2] for p1, p2 in zip(inx[:-1], inx[1:])] conn.extend(row) aux = nm.empty(len(conn), dtype=nm.int32) aux.fill(ib) mat_ids.append(aux) conns.append(offset + nm.array(conn, dtype=nm.int32)) offset += n_nod mesh = Mesh.from_data('control_points', coors, None, conns, mat_ids, descs) return mesh
def create_mesh_from_control_points( self ): offset = 0 dim = self.spbs[0].cxyz.shape[1] coors = nm.empty((0, dim), dtype=nm.float64) conns = [] mat_ids = [] descs = [] for ib, spb in enumerate( self.spbs ): n_nod = spb.cxyz.shape[0] coors = nm.concatenate( (coors, spb.cxyz), 0 ) descs.append( '3_2' ) conn = [] for ij in range( spb.cpi.shape[1] ): for ik in range( spb.cpi.shape[2] ): inx = spb.cpi[:,ij,ik] row = [[p1, p2] for p1, p2 in zip( inx[:-1], inx[1:] )] conn.extend( row ) for ij in range( spb.cpi.shape[0] ): for ik in range( spb.cpi.shape[2] ): inx = spb.cpi[ij,:,ik] row = [[p1, p2] for p1, p2 in zip( inx[:-1], inx[1:] )] conn.extend( row ) for ij in range( spb.cpi.shape[0] ): for ik in range( spb.cpi.shape[1] ): inx = spb.cpi[ij,ik,:] row = [[p1, p2] for p1, p2 in zip( inx[:-1], inx[1:] )] conn.extend( row ) aux = nm.empty(len(conn), dtype=nm.int32) aux.fill(ib) mat_ids.append(aux) conns.append( offset + nm.array( conn, dtype = nm.int32 ) ) offset += n_nod mesh = Mesh.from_data('control_points', coors, None, conns, mat_ids, descs) return mesh
def from_conf(conf, init_fields=True, init_equations=True, init_solvers=True): if conf.options.get("absolute_mesh_path", False): conf_dir = None else: conf_dir = op.dirname(conf.funmod.__file__) functions = Functions.from_conf(conf.functions) mesh = Mesh.from_file(conf.filename_mesh, prefix_dir=conf_dir) trans_mtx = conf.options.get("mesh_coors_transform", None) if trans_mtx is not None: mesh.transform_coors(trans_mtx) domain = Domain(mesh.name, mesh) if conf.options.get("ulf", False): domain.mesh.coors_act = domain.mesh.coors.copy() obj = Problem( "problem_from_conf", conf=conf, functions=functions, domain=domain, auto_conf=False, auto_solvers=False ) obj.set_regions(conf.regions, obj.functions) obj.clear_equations() if init_fields: obj.set_fields(conf.fields) if init_equations: obj.set_equations(conf.equations, user={"ts": obj.ts}) if init_solvers: obj.set_solvers(conf.solvers, conf.options) return obj
def define(grid0=100, filename_mesh=None): eps0 = 0.01 / grid0 if filename_mesh is None: filename_mesh = osp.join(data_dir, 'piezo_mesh_micro_dfc.vtk') mesh = Mesh.from_file(filename_mesh) n_conduct = len(nm.unique(mesh.cmesh.cell_groups)) - 2 sym_eye = 'nm.array([1,1,0])' if mesh.dim == 2 else\ 'nm.array([1,1,1,0,0,0])' bbox = mesh.get_bounding_box() regions = define_box_regions(mesh.dim, bbox[0], bbox[1], eps=1e-3) regions.update({ 'Y': 'all', # matrix 'Ym': 'cells of group 1', 'Ym_left': ('r.Ym *v r.Left', 'vertex'), 'Ym_right': ('r.Ym *v r.Right', 'vertex'), 'Ym_bottom': ('r.Ym *v r.Bottom', 'vertex'), 'Ym_top': ('r.Ym *v r.Top', 'vertex'), 'Ym_far': ('r.Ym *v r.Far', 'vertex'), 'Ym_near': ('r.Ym *v r.Near', 'vertex'), 'Gamma_mc': ('r.Ym *v r.Yc', 'facet', 'Ym'), # channel / inclusion 'Yc': 'cells of group 2', 'Yc0': ('r.Yc -v r.Gamma_cm', 'vertex'), 'Gamma_cm': ('r.Ym *v r.Yc', 'facet', 'Yc'), }) print('number of cnonductors: %d' % n_conduct) regions.update({ 'Yms': ('r.Ym +v r.Ys', 'cell'), 'Yms_left': ('r.Yms *v r.Left', 'vertex'), 'Yms_right': ('r.Yms *v r.Right', 'vertex'), 'Yms_bottom': ('r.Yms *v r.Bottom', 'vertex'), 'Yms_top': ('r.Yms *v r.Top', 'vertex'), 'Yms_far': ('r.Yms *v r.Far', 'vertex'), 'Yms_near': ('r.Yms *v r.Near', 'vertex'), 'Gamma_ms': ('r.Ym *v r.Ys', 'facet', 'Ym'), 'Gamma_msc': ('r.Yms *v r.Yc', 'facet', 'Yms'), 'Ys': (' +v '.join(['r.Ys%d' % k for k in range(n_conduct)]), 'cell'), }) options = { 'coefs_filename': 'coefs_poropiezo_%d' % (grid0), 'volume': { 'variables': ['svar'], 'expression': 'd_volume.i2.Y(svar)', }, 'coefs': 'coefs', 'requirements': 'requirements', 'output_dir': osp.join(data_dir, 'results'), 'ls': 'ls', 'file_per_var': True, 'absolute_mesh_path': True, 'multiprocessing': False, 'recovery_hook': recovery_micro_dfc, } fields = { 'displacement': ('real', 'vector', 'Yms', 1), 'potential': ('real', 'scalar', 'Ym', 1), 'sfield': ('real', 'scalar', 'Y', 1), } variables = { # displacement 'u': ('unknown field', 'displacement'), 'v': ('test field', 'displacement', 'u'), 'Pi_u': ('parameter field', 'displacement', 'u'), 'U1': ('parameter field', 'displacement', '(set-to-None)'), 'U2': ('parameter field', 'displacement', '(set-to-None)'), # potential 'r': ('unknown field', 'potential'), 's': ('test field', 'potential', 'r'), 'Pi_r': ('parameter field', 'potential', 'r'), 'R1': ('parameter field', 'potential', '(set-to-None)'), 'R2': ('parameter field', 'potential', '(set-to-None)'), # aux variable 'svar': ('parameter field', 'sfield', '(set-to-None)'), } epbcs, periodic = get_periodic_bc([('u', 'Yms'), ('r', 'Ym')]) mat_g_sc, mat_d_sc = eps0, eps0**2 # BaTiO3 - Miara, Rohan, ... doi: 10.1016/j.jmps.2005.05.006 materials = { 'matrix': ({ 'D': { 'Ym': nm.array([[1.504, 0.656, 0.659, 0, 0, 0], [0.656, 1.504, 0.659, 0, 0, 0], [0.659, 0.659, 1.455, 0, 0, 0], [0, 0, 0, 0.424, 0, 0], [0, 0, 0, 0, 0.439, 0], [0, 0, 0, 0, 0, 0.439]]) * 1e11, } }, ), 'piezo': ({ 'g': nm.array([[0, 0, 0, 0, 11.404, 0], [0, 0, 0, 0, 0, 11.404], [-4.322, -4.322, 17.360, 0, 0, 0]]) / mat_g_sc, 'd': nm.array([[1.284, 0, 0], [0, 1.284, 0], [0, 0, 1.505]]) * 1e-8 / mat_d_sc, }, ), 'fluid': ({ 'gamma': 1.0 / 2.15e9 }, ), } functions = { 'match_x_plane': (per.match_x_plane, ), 'match_y_plane': (per.match_y_plane, ), 'match_z_plane': (per.match_z_plane, ), } ebcs = { 'fixed_u': ('Corners', { 'u.all': 0.0 }), 'fixed_r': ('Gamma_ms', { 'r.all': 0.0 }), } integrals = { 'i2': 2, 'i5': 5, } solvers = { 'ls': ('ls.scipy_direct', {}), 'ns_em6': ('nls.newton', { 'i_max': 1, 'eps_a': 1e-6, 'eps_r': 1e-6, 'problem': 'nonlinear' }), 'ns_em3': ('nls.newton', { 'i_max': 1, 'eps_a': 1e-3, 'eps_r': 1e-6, 'problem': 'nonlinear' }), } coefs = { # homogenized elasticity, see eq. (46)_1 'A': { 'requires': ['c.A1', 'c.A2'], 'expression': 'c.A1 + c.A2', 'class': cb.CoefEval, }, 'A1': { 'status': 'auxiliary', 'requires': ['pis_u', 'corrs_rs'], 'expression': 'dw_lin_elastic.i2.Yms(matrix.D, U1, U2)', 'set_variables': [('U1', ('corrs_rs', 'pis_u'), 'u'), ('U2', ('corrs_rs', 'pis_u'), 'u')], 'class': cb.CoefSymSym, }, 'A2': { 'status': 'auxiliary', 'requires': ['corrs_rs'], 'expression': 'dw_diffusion.i2.Ym(piezo.d, R1, R2)', 'set_variables': [('R1', 'corrs_rs', 'r'), ('R2', 'corrs_rs', 'r')], 'class': cb.CoefSymSym, }, # homogenized Biot coefficient, see eq. (46)_2 'B': { 'requires': ['c.Phi', 'c.B1', 'c.B2'], 'expression': 'c.B1 - c.B2 + c.Phi * %s' % sym_eye, 'class': cb.CoefEval, }, 'B1': { 'status': 'auxiliary', 'requires': ['pis_u', 'corrs_p'], 'expression': 'dw_lin_elastic.i2.Yms(matrix.D, U1, U2)', 'set_variables': [('U1', 'corrs_p', 'u'), ('U2', 'pis_u', 'u')], 'class': cb.CoefSym, }, 'B2': { 'status': 'auxiliary', 'requires': ['pis_u', 'corrs_p'], 'expression': 'dw_piezo_coupling.i2.Ym(piezo.g, U1, R1)', 'set_variables': [('R1', 'corrs_p', 'r'), ('U1', 'pis_u', 'u')], 'class': cb.CoefSym, }, # homogenized compressibility coefficient, see eq. (46)_6 'M': { 'requires': ['c.Phi', 'c.N'], 'expression': 'c.N + c.Phi * %e' % materials['fluid'][0]['gamma'], 'class': cb.CoefEval, }, 'N': { 'status': 'auxiliary', 'requires': ['corrs_p'], 'expression': 'dw_surface_ltr.i2.Gamma_msc(U1)', 'set_variables': [('U1', 'corrs_p', 'u')], 'class': cb.CoefOne, }, 'Phi': { 'requires': ['c.vol'], 'expression': 'c.vol["fraction_Yc"]', 'class': cb.CoefEval, }, # volume fractions of Ym, Yc, Ys1, Ys2, ... 'vol': { 'regions': ['Ym', 'Yc'] + ['Ys%d' % k for k in range(n_conduct)], 'expression': 'd_volume.i2.%s(svar)', 'class': cb.VolumeFractions, }, 'eps0': { 'requires': [], 'expression': '%e' % eps0, 'class': cb.CoefEval, }, 'filenames': {}, } requirements = { 'pis_u': { 'variables': ['u'], 'class': cb.ShapeDimDim, }, 'pis_r': { 'variables': ['r'], 'class': cb.ShapeDim, }, # local subproblem defined by eq. (41) 'corrs_rs': { 'requires': ['pis_u'], 'ebcs': ['fixed_u', 'fixed_r'], 'epbcs': periodic['per_u'] + periodic['per_r'], 'is_linear': True, 'equations': { 'eq1': """dw_lin_elastic.i2.Yms(matrix.D, v, u) - dw_piezo_coupling.i2.Ym(piezo.g, v, r) = - dw_lin_elastic.i2.Yms(matrix.D, v, Pi_u)""", 'eq2': """ - dw_piezo_coupling.i2.Ym(piezo.g, u, s) - dw_diffusion.i2.Ym(piezo.d, s, r) = dw_piezo_coupling.i2.Ym(piezo.g, Pi_u, s)""", }, 'set_variables': [('Pi_u', 'pis_u', 'u')], 'class': cb.CorrDimDim, 'save_name': 'corrs_rs_%d' % grid0, 'dump_variables': ['u', 'r'], 'solvers': { 'ls': 'ls', 'nls': 'ns_em3' }, }, # local subproblem defined by eq. (42) 'corrs_p': { 'requires': [], 'ebcs': ['fixed_u', 'fixed_r'], 'epbcs': periodic['per_u'] + periodic['per_r'], 'is_linear': True, 'equations': { 'eq1': """dw_lin_elastic.i2.Yms(matrix.D, v, u) - dw_piezo_coupling.i2.Ym(piezo.g, v, r) = dw_surface_ltr.i2.Gamma_msc(v)""", 'eq2': """ - dw_piezo_coupling.i2.Ym(piezo.g, u, s) - dw_diffusion.i2.Ym(piezo.d, s, r) = 0""" }, 'class': cb.CorrOne, 'save_name': 'corrs_p_%d' % grid0, 'dump_variables': ['u', 'r'], 'solvers': { 'ls': 'ls', 'nls': 'ns_em6' }, }, # local subproblem defined by eq. (43) 'corrs_rho': { 'requires': [], 'ebcs': ['fixed_u', 'fixed_r'], 'epbcs': periodic['per_u'] + periodic['per_r'], 'is_linear': True, 'equations': { 'eq1': """dw_lin_elastic.i2.Yms(matrix.D, v, u) - dw_piezo_coupling.i2.Ym(piezo.g, v, r) = 0""", 'eq2': """ - dw_piezo_coupling.i2.Ym(piezo.g, u, s) - dw_diffusion.i2.Ym(piezo.d, s, r) = - dw_surface_integrate.i2.Gamma_mc(s)""" }, 'class': cb.CorrOne, 'save_name': 'corrs_p_%d' % grid0, 'dump_variables': ['u', 'r'], 'solvers': { 'ls': 'ls', 'nls': 'ns_em6' }, }, } for k in range(n_conduct): sk = '%d' % k regions.update({ 'Ys' + sk: 'cells of group %d' % (3 + k), 'Gamma_s' + sk: ('r.Ym *v r.Ys' + sk, 'facet', 'Ym'), }) materials['matrix'][0]['D'].update({ 'Ys' + sk: stiffness_from_youngpoisson(3, 200e9, 0.25), }) ebcs.update({ 'fixed_r1_k_' + sk: ('Gamma_s' + sk, { 'r.0': 1.0 }), 'fixed_r0_k_' + sk: ('Gamma_s' + sk, { 'r.0': 0.0 }), }) fixed_r0_k = [ 'fixed_r0_k_%d' % ii for ii in range(n_conduct) if not ii == k ] # local subproblems defined for conductors, see eq. (44) requirements.update({ 'corrs_k' + sk: { 'requires': ['pis_r'], 'ebcs': ['fixed_u', 'fixed_r1_k_' + sk] + fixed_r0_k, 'epbcs': periodic['per_u'] + periodic['per_r'], 'is_linear': True, 'equations': { 'eq1': """dw_lin_elastic.i2.Yms(matrix.D, v, u) - dw_piezo_coupling.i2.Ym(piezo.g, v, r) = 0""", 'eq2': """ - dw_piezo_coupling.i2.Ym(piezo.g, u, s) - dw_diffusion.i2.Ym(piezo.d, s, r) = 0""" }, 'class': cb.CorrOne, 'save_name': 'corrs_k' + sk + '_%d' % grid0, 'dump_variables': ['u', 'r'], 'solvers': { 'ls': 'ls', 'nls': 'ns_em6' }, }, }) coefs.update({ # homogenized coefficient (46)_3 'H' + sk: { 'requires': ['c.H1_' + sk, 'c.H2_' + sk], 'expression': 'c.H1_%s - c.H2_%s' % (sk, sk), 'class': cb.CoefEval, }, 'H1_' + sk: { 'status': 'auxiliary', 'requires': ['pis_u', 'corrs_k' + sk], 'expression': 'dw_lin_elastic.i2.Yms(matrix.D, U1, U2)', 'set_variables': [('U1', 'corrs_k' + sk, 'u'), ('U2', 'pis_u', 'u')], 'class': cb.CoefSym, }, 'H2_' + sk: { 'status': 'auxiliary', 'requires': ['pis_u', 'corrs_k' + sk], 'expression': 'dw_piezo_coupling.i2.Ym(piezo.g, U1, R1)', 'set_variables': [('R1', 'corrs_k' + sk, 'r'), ('U1', 'pis_u', 'u')], 'class': cb.CoefSym, }, # homogenized coefficient (46)_7 'Z' + sk: { 'requires': ['corrs_k' + sk], 'expression': 'dw_surface_ltr.i2.Gamma_msc(U1)', 'set_variables': [('U1', 'corrs_k' + sk, 'u')], 'class': cb.CoefOne, }, }) return locals()
def gen_mesh_from_poly(filename, verbose=True): """ Import mesh generated by tetgen or triangle. Parameters ---------- filename : string file name Returns ------- mesh : Mesh instance triangular or tetrahedral mesh """ def getnodes(fnods, up): f = file(fnods) l = [int(x) for x in f.readline().split()] npoints, dim, nattrib, nbound = l if verbose: up.init(npoints) nodes = [] for line in f: if line[0] == "#": continue l = [float(x) for x in line.split()] l = l[:(dim + 1)] l[0] = int(l[0]) nodes.append(tuple(l)) assert l[0] == len(nodes) assert npoints == len(nodes) return nodes def getele(fele, up): f = file(fele) l = [int(x) for x in f.readline().split()] nele, nnod, nattrib = l #we have either linear or quadratic tetrahedra: if nnod in [4, 10]: elem = 'tetra' linear = (nnod == 4) if nnod in [3, 7]: elem = 'tri' linear = (nnod == 3) # if nattrib!=1: # raise "tetgen didn't assign an entity number to each element (option -A)" els = [] regions = {} for line in f: if line[0] == "#": continue l = [int(x) for x in line.split()] if elem == 'tri': if linear: assert (len(l) - 1 - nattrib) == 3 els.append((l[0], l[1], l[2], l[3])) regionnum = l[5] else: assert len(l) - 2 == 10 els.append((l[0], 54, l[1], l[2], l[3], l[4], l[5], l[6], l[7], l[8], l[9], l[10])) regionnum = l[11] if elem == 'tetra': if linear: assert len(l) - 2 == 4 els.append((l[0], 54, l[1], l[2], l[3], l[4])) regionnum = l[5] else: assert len(l) - 2 == 10 els.append((l[0], 54, l[1], l[2], l[3], l[4], l[5], l[6], l[7], l[8], l[9], l[10])) regionnum = l[11] if regionnum == 0: print "see %s, element # %d" % (fele, l[0]) raise "there are elements not belonging to any physical entity" if regions.has_key(regionnum): regions[regionnum].append(l[0]) else: regions[regionnum] = [l[0]] assert l[0] == len(els) if verbose: up.update(l[0]) return els, regions, linear def getBCfaces(ffaces, up): f = file(ffaces) l = [int(x) for x in f.readline().split()] nfaces, nattrib = l if nattrib != 1: raise "tetgen didn't assign an entity number to each face \ (option -A)" if verbose: up.init(nfaces) faces = {} for line in f: if line[0] == "#": continue l = [int(x) for x in line.split()] assert len(l) == 5 regionnum = l[4] if regionnum == 0: continue if faces.has_key(regionnum): faces[regionnum].append((l[1], l[2], l[3])) else: faces[regionnum] = [(l[1], l[2], l[3])] if verbose: up.update(l[0]) return faces def calculatexyz(nodes, els): """Calculate the missing xyz values in place""" def avg(i, j, n4, nodes): a = nodes[n4[i - 1] - 1] b = nodes[n4[j - 1] - 1] return (a[1] + b[1]) / 2, (a[2] + b[2]) / 2, (a[3] + b[3]) / 2 def getxyz(i, n4, nodes): if i + 5 == 5: return avg(1, 2, n4, nodes) if i + 5 == 6: return avg(2, 3, n4, nodes) if i + 5 == 7: return avg(1, 3, n4, nodes) if i + 5 == 8: return avg(1, 4, n4, nodes) if i + 5 == 9: return avg(2, 4, n4, nodes) if i + 5 == 10: return avg(3, 4, n4, nodes) raise "wrong topology" for e in els: n4 = e[2:2 + 4] n6 = e[2 + 4:2 + 4 + 10] for i, n in enumerate(n6): x, y, z = getxyz(i, n4, nodes) nodes[n - 1] = (n, x, y, z) if verbose: print "Reading geometry from poly file..." m = Mesh() m.nodes = getnodes(filename + ".node") m.elements, m.regions, lin = getele(filename + ".ele") if not lin: #tetgen doesn't compute xyz coordinates of the aditional 6 nodes #(only of the 4 corner nodes) in tetrahedra. calculatexyz(m.nodes, m.elements) m.faces = getBCfaces(filename + ".face") return m
def linearize(self, dofs, min_level=0, max_level=1, eps=1e-4): """ Linearize the solution for post-processing. Parameters ---------- dofs : array, shape (n_nod, n_component) The array of DOFs reshaped so that each column corresponds to one component. min_level : int The minimum required level of mesh refinement. max_level : int The maximum level of mesh refinement. eps : float The relative tolerance parameter of mesh adaptivity. Returns ------- mesh : Mesh instance The adapted, nonconforming, mesh. vdofs : array The DOFs defined in vertices of `mesh`. levels : array of ints The refinement level used for each element group. """ assert_(dofs.ndim == 2) n_nod, dpn = dofs.shape assert_(n_nod == self.n_nod) assert_(dpn == self.shape[0]) vertex_coors = self.coors[:self.n_vertex_dof, :] coors = [] vdofs = [] conns = [] mat_ids = [] levels = [] offset = 0 for ig, ap in self.aps.iteritems(): ps = ap.interp.poly_spaces['v'] gps = ap.interp.gel.interp.poly_spaces['v'] group = self.domain.groups[ig] vertex_conn = ap.econn[:, :group.shape.n_ep] eval_dofs = get_eval_dofs(dofs, ap.econn, ps, ori=ap.ori) eval_coors = get_eval_coors(vertex_coors, vertex_conn, gps) (level, _coors, conn, _vdofs, _mat_ids) = create_output(eval_dofs, eval_coors, group.shape.n_el, ps, min_level=min_level, max_level=max_level, eps=eps) _mat_ids[:] = self.domain.mesh.mat_ids[ig][0] coors.append(_coors) vdofs.append(_vdofs) conns.append(conn + offset) mat_ids.append(_mat_ids) levels.append(level) offset += _coors.shape[0] coors = nm.concatenate(coors, axis=0) vdofs = nm.concatenate(vdofs, axis=0) mesh = Mesh.from_data('linearized_mesh', coors, None, conns, mat_ids, self.domain.mesh.descs) return mesh, vdofs, levels
def gen_mesh_from_poly(filename, verbose=True): """ Import mesh generated by tetgen or triangle. Parameters ---------- filename : string file name Returns ------- mesh : Mesh instance triangular or tetrahedral mesh """ def getnodes(fnods,up): f=file(fnods) l=[int(x) for x in f.readline().split()] npoints,dim,nattrib,nbound=l if verbose: up.init(npoints) nodes=[] for line in f: if line[0]=="#": continue l=[float(x) for x in line.split()] l = l[:(dim + 1)] l[0]=int(l[0]) nodes.append(tuple(l)) assert l[0]==len(nodes) assert npoints==len(nodes) return nodes def getele(fele,up): f=file(fele) l=[int(x) for x in f.readline().split()] nele,nnod,nattrib=l #we have either linear or quadratic tetrahedra: if nnod in [4,10]: elem = 'tetra' linear = (nnod == 4) if nnod in [3, 7]: elem = 'tri' linear = (nnod == 3) # if nattrib!=1: # raise "tetgen didn't assign an entity number to each element (option -A)" els=[] regions={} for line in f: if line[0]=="#": continue l=[int(x) for x in line.split()] if elem == 'tri': if linear: assert (len(l) - 1 - nattrib) == 3 els.append((l[0],l[1],l[2],l[3])) regionnum=l[5] else: assert len(l)-2 == 10 els.append((l[0],54,l[1],l[2],l[3],l[4], l[5],l[6],l[7],l[8],l[9],l[10])) regionnum=l[11] if elem == 'tetra': if linear: assert len(l)-2 == 4 els.append((l[0],54,l[1],l[2],l[3],l[4])) regionnum=l[5] else: assert len(l)-2 == 10 els.append((l[0],54,l[1],l[2],l[3],l[4], l[5],l[6],l[7],l[8],l[9],l[10])) regionnum=l[11] if regionnum==0: print "see %s, element # %d"%(fele,l[0]) raise "there are elements not belonging to any physical entity" if regions.has_key(regionnum): regions[regionnum].append(l[0]) else: regions[regionnum]=[l[0]] assert l[0]==len(els) if verbose: up.update(l[0]) return els,regions,linear def getBCfaces(ffaces,up): f=file(ffaces) l=[int(x) for x in f.readline().split()] nfaces,nattrib=l if nattrib!=1: raise "tetgen didn't assign an entity number to each face \ (option -A)" if verbose: up.init(nfaces) faces={} for line in f: if line[0]=="#": continue l=[int(x) for x in line.split()] assert len(l)==5 regionnum=l[4] if regionnum==0: continue if faces.has_key(regionnum): faces[regionnum].append((l[1],l[2],l[3])) else: faces[regionnum]=[(l[1],l[2],l[3])] if verbose: up.update(l[0]) return faces def calculatexyz(nodes, els): """Calculate the missing xyz values in place""" def avg(i,j,n4,nodes): a=nodes[n4[i-1]-1] b=nodes[n4[j-1]-1] return (a[1]+b[1])/2, (a[2]+b[2])/2, (a[3]+b[3])/2 def getxyz(i,n4,nodes): if i+5==5: return avg(1,2,n4,nodes) if i+5==6: return avg(2,3,n4,nodes) if i+5==7: return avg(1,3,n4,nodes) if i+5==8: return avg(1,4,n4,nodes) if i+5==9: return avg(2,4,n4,nodes) if i+5==10: return avg(3,4,n4,nodes) raise "wrong topology" for e in els: n4=e[2:2+4] n6=e[2+4:2+4+10] for i,n in enumerate(n6): x,y,z=getxyz(i,n4,nodes) nodes[n-1]=(n,x,y,z) if verbose: print "Reading geometry from poly file..." m=Mesh() m.nodes=getnodes(filename+".node") m.elements,m.regions, lin=getele(filename+".ele") if not lin: #tetgen doesn't compute xyz coordinates of the aditional 6 nodes #(only of the 4 corner nodes) in tetrahedra. calculatexyz(m.nodes,m.elements) m.faces=getBCfaces(filename+".face") return m
def gen_mesh_from_goem(geo, a=None, quadratic=False, verbose=True, refine=False, polyfilename='./meshgen.poly', out='mesh', **kwargs): """ Runs mesh generator - tetgen for 3D or triangle for 2D meshes. Parameters ---------- geo : geometry geometry description a : int, optional a maximum area/volume constraint quadratic : bool, optional set True for quadratic elements verbose : bool, optional detailed information refine : bool, optional refines mesh Returns ------- mesh : Mesh instance triangular or tetrahedral mesh """ import os.path as op import pexpect # write geometry to poly file geo.to_poly_file(polyfilename) if not refine: params = "-Apq" else: params = "-Arq" if verbose: params = params + " -Q" if a != None and not refine: params = params + " -a%f" % (a) if refine: params = params + " -a" if quadratic: params = params + " -o2" params = params + " %s" % (polyfilename) meshgen_call = {2: 'triangle', 3: 'tetgen'} cmd = "%s %s" % (meshgen_call[geo.dim], params) if verbose: print "Generating mesh using", cmd if geo.dim == 2: p=pexpect.run(cmd, timeout=None) bname, ext = op.splitext(polyfilename) mesh = Mesh.from_file(bname + '.1.node') mesh.write(bname + '.' + out) if geo.dim == 3: p=pexpect.spawn(cmd, timeout=None) if not refine: p.expect("Opening %s." % (polyfilename)) else: p.expect("Opening %s.node.\r\n" % (polyfilename)) p.expect("Opening %s.ele.\r\n" % (polyfilename)) p.expect("Opening %s.face.\r\n" % (polyfilename)) p.expect("Opening %s.vol." % (polyfilename)) assert p.before == "" p.expect(pexpect.EOF) if p.before != "\r\n": print p.before raise "Error when running mesh generator (see above for output): %s" % cmd
def gen_tiled_mesh(mesh, grid=None, scale=1.0, eps=1e-6, ret_ndmap=False): """ Generate a new mesh by repeating a given periodic element along each axis. Parameters ---------- mesh : Mesh instance The input periodic FE mesh. grid : array Number of repetition along each axis. scale : float, optional Scaling factor. eps : float, optional Tolerance for boundary detection. ret_ndmap : bool, optional If True, return global node map. Returns ------- mesh_out : Mesh instance FE mesh. ndmap : array Maps: actual node id --> node id in the reference cell. """ bbox = mesh.get_bounding_box() if grid is None: iscale = max(int(1.0 / scale), 1) grid = [iscale] * mesh.dim conns = mesh.conns[0] for ii in mesh.conns[1:]: conns = nm.vstack((conns, ii)) mat_ids = mesh.mat_ids[0] for ii in mesh.mat_ids[1:]: mat_ids = nm.hstack((mat_ids, ii)) coors = mesh.coors ngrps = mesh.ngroups nrep = nm.prod(grid) ndmap = None output('repeating %s ...' % grid) nblk = 1 for ii, gr in enumerate(grid): if ret_ndmap: (conns, coors, ngrps, ndmap0) = tiled_mesh1d(conns, coors, ngrps, ii, gr, bbox.transpose()[ii], eps=eps, ndmap=ndmap) ndmap = ndmap0 else: conns, coors, ngrps = tiled_mesh1d(conns, coors, ngrps, ii, gr, bbox.transpose()[ii], eps=eps) nblk *= gr output('...done') mat_ids = nm.tile(mat_ids, (nrep,)) mesh_out = Mesh.from_data('tiled mesh', coors * scale, ngrps, [conns], [mat_ids], [mesh.descs[0]]) if ret_ndmap: return mesh_out, ndmap else: return mesh_out
def save_state(self, filename, state=None, out=None, fill_value=None, post_process_hook=None, linearization=None, file_per_var=False, **kwargs): """ Parameters ---------- file_per_var : bool or None If True, data of each variable are stored in a separate file. If None, it is set to the application option value. linearization : Struct or None The linearization configuration for higher order approximations. If its kind is 'adaptive', `file_per_var` is assumed True. """ linearization = get_default(linearization, self.linearization) if linearization.kind != 'adaptive': file_per_var = get_default(file_per_var, self.file_per_var) else: file_per_var = True extend = not file_per_var if (out is None) and (state is not None): out = state.create_output_dict(fill_value=fill_value, extend=extend, linearization=linearization) if post_process_hook is not None: out = post_process_hook(out, self, state, extend=extend) if linearization.kind == 'adaptive': for key, val in out.iteritems(): mesh = val.get('mesh', self.domain.mesh) aux = io.edit_filename(filename, suffix='_' + val.var_name) mesh.write(aux, io='auto', out={key : val}, float_format=self.float_format, **kwargs) if hasattr(val, 'levels'): output('max. refinement per group:', val.levels) elif file_per_var: meshes = {} if self.equations is None: varnames = {} for key, val in out.iteritems(): varnames[val.var_name] = 1 varnames = varnames.keys() outvars = self.create_variables(varnames) itervars = outvars.__iter__ else: itervars = self.equations.variables.iter_state for var in itervars(): rname = var.field.region.name if meshes.has_key(rname): mesh = meshes[rname] else: mesh = Mesh.from_region(var.field.region, self.domain.mesh, localize=True, is_surface=var.is_surface) meshes[rname] = mesh vout = {} for key, val in out.iteritems(): try: if val.var_name == var.name: vout[key] = val except AttributeError: msg = 'missing var_name attribute in output!' raise ValueError(msg) aux = io.edit_filename(filename, suffix='_' + var.name) mesh.write(aux, io='auto', out=vout, float_format=self.float_format, **kwargs) else: mesh = out.pop('__mesh__', self.domain.mesh) mesh.write(filename, io='auto', out=out, float_format=self.float_format, **kwargs)
def gen_mesh_from_voxels(voxels, dims, etype='q'): """ Generate FE mesh from voxels (volumetric data). Parameters ---------- voxels : array Voxel matrix, 1=material. dims : array Size of one voxel. etype : integer, optional 'q' - quadrilateral or hexahedral elements 't' - triangular or tetrahedral elements Returns ------- mesh : Mesh instance Finite element mesh. """ dims = nm.array(dims).squeeze() dim = len(dims) nddims = nm.array(voxels.shape) + 2 nodemtx = nm.zeros(nddims, dtype=nm.int32) if dim == 2: #iy, ix = nm.where(voxels.transpose()) iy, ix = nm.where(voxels) nel = ix.shape[0] if etype == 'q': nodemtx[ix,iy] += 1 nodemtx[ix + 1,iy] += 1 nodemtx[ix + 1,iy + 1] += 1 nodemtx[ix,iy + 1] += 1 elif etype == 't': nodemtx[ix,iy] += 2 nodemtx[ix + 1,iy] += 1 nodemtx[ix + 1,iy + 1] += 2 nodemtx[ix,iy + 1] += 1 nel *= 2 elif dim == 3: #iy, ix, iz = nm.where(voxels.transpose(1, 0, 2)) iy, ix, iz = nm.where(voxels) nel = ix.shape[0] if etype == 'q': nodemtx[ix,iy,iz] += 1 nodemtx[ix + 1,iy,iz] += 1 nodemtx[ix + 1,iy + 1,iz] += 1 nodemtx[ix,iy + 1,iz] += 1 nodemtx[ix,iy,iz + 1] += 1 nodemtx[ix + 1,iy,iz + 1] += 1 nodemtx[ix + 1,iy + 1,iz + 1] += 1 nodemtx[ix,iy + 1,iz + 1] += 1 elif etype == 't': nodemtx[ix,iy,iz] += 6 nodemtx[ix + 1,iy,iz] += 2 nodemtx[ix + 1,iy + 1,iz] += 2 nodemtx[ix,iy + 1,iz] += 2 nodemtx[ix,iy,iz + 1] += 2 nodemtx[ix + 1,iy,iz + 1] += 2 nodemtx[ix + 1,iy + 1,iz + 1] += 6 nodemtx[ix,iy + 1,iz + 1] += 2 nel *= 6 else: msg = 'incorrect voxel dimension! (%d)' % dim raise ValueError(msg) ndidx = nm.where(nodemtx) coors = nm.array(ndidx).transpose() * dims nnod = coors.shape[0] nodeid = -nm.ones(nddims, dtype=nm.int32) nodeid[ndidx] = nm.arange(nnod) # generate elements if dim == 2: elems = nm.array([nodeid[ix,iy], nodeid[ix + 1,iy], nodeid[ix + 1,iy + 1], nodeid[ix,iy + 1]]).transpose() elif dim == 3: elems = nm.array([nodeid[ix,iy,iz], nodeid[ix + 1,iy,iz], nodeid[ix + 1,iy + 1,iz], nodeid[ix,iy + 1,iz], nodeid[ix,iy,iz + 1], nodeid[ix + 1,iy,iz + 1], nodeid[ix + 1,iy + 1,iz + 1], nodeid[ix,iy + 1,iz + 1]]).transpose() if etype == 't': elems = elems_q2t(elems) eid = etype + str(dim) eltab = {'q2': 4, 'q3': 8, 't2': 3, 't3': 4} mesh = Mesh.from_data('voxel_data', coors, nm.ones((nnod,), dtype=nm.int32), [nm.ascontiguousarray(elems)], [nm.ones((nel,), dtype=nm.int32)], ['%d_%d' % (dim, eltab[eid])]) return mesh
def define(eps0=1e-3, filename_mesh='meshes/3d/piezo_mesh_micro.vtk'): mesh = Mesh.from_file(filename_mesh) bbox = mesh.get_bounding_box() regions = define_box_regions(mesh.dim, bbox[0], bbox[1], eps=1e-3) regions.update({ 'Ymc': 'all', # matrix 'Ym': 'cells of group 1', 'Ym_left': ('r.Ym *v r.Left', 'vertex'), 'Ym_right': ('r.Ym *v r.Right', 'vertex'), 'Ym_bottom': ('r.Ym *v r.Bottom', 'vertex'), 'Ym_top': ('r.Ym *v r.Top', 'vertex'), 'Ym_far': ('r.Ym *v r.Far', 'vertex'), 'Ym_near': ('r.Ym *v r.Near', 'vertex'), 'Gamma_ms': ('r.Ym *v r.Yc', 'facet', 'Ym'), # conductors 'Yc': ('r.Yc1 +c r.Yc2', 'cell'), 'Yc1': 'cells of group 2', 'Yc2': 'cells of group 3', 'Gamma_s1': ('r.Ym *v r.Yc1', 'facet', 'Ym'), 'Gamma_s2': ('r.Ym *v r.Yc2', 'facet', 'Ym'), }) options = { 'coefs_filename': 'coefs_piezo', 'volume': { 'value': nm.prod(bbox[1] - bbox[0]) }, 'coefs': 'coefs', 'requirements': 'requirements', 'output_dir': 'output', 'file_per_var': True, 'absolute_mesh_path': True, 'multiprocessing': False, 'recovery_hook': recovery_micro, } fields = { 'displacement': ('real', 'vector', 'Ymc', 1), 'potential': ('real', 'scalar', 'Ym', 1), 'sfield': ('real', 'scalar', 'Ymc', 1), } variables = { # displacement 'u': ('unknown field', 'displacement'), 'v': ('test field', 'displacement', 'u'), 'Pi_u': ('parameter field', 'displacement', 'u'), 'U1': ('parameter field', 'displacement', '(set-to-None)'), 'U2': ('parameter field', 'displacement', '(set-to-None)'), # potential 'r': ('unknown field', 'potential'), 's': ('test field', 'potential', 'r'), 'Pi_r': ('parameter field', 'potential', 'r'), 'R1': ('parameter field', 'potential', '(set-to-None)'), 'R2': ('parameter field', 'potential', '(set-to-None)'), # auxiliary 'svar': ('parameter field', 'sfield', '(set-to-None)'), } epbcs = { 'p_ux': (['Left', 'Right'], { 'u.all': 'u.all' }, 'match_x_plane'), 'p_uy': (['Near', 'Far'], { 'u.all': 'u.all' }, 'match_y_plane'), 'p_uz': (['Bottom', 'Top'], { 'u.all': 'u.all' }, 'match_z_plane'), 'p_rx': (['Ym_left', 'Ym_right'], { 'r.0': 'r.0' }, 'match_x_plane'), 'p_ry': (['Ym_near', 'Ym_far'], { 'r.0': 'r.0' }, 'match_y_plane'), 'p_rz': (['Ym_bottom', 'Ym_top'], { 'r.0': 'r.0' }, 'match_z_plane'), } periodic = { 'per_u': ['per_u_x', 'per_u_y', 'per_u_z'], 'per_r': ['per_r_x', 'per_r_y', 'per_r_z'], } # rescale piezoelectric material parameters mat_g_sc, mat_d_sc = (eps0, eps0**2) materials = { 'elastic': ({ 'D': { 'Ym': nm.array([[1.504, 0.656, 0.659, 0, 0, 0], [0.656, 1.504, 0.659, 0, 0, 0], [0.659, 0.659, 1.455, 0, 0, 0], [0, 0, 0, 0.424, 0, 0], [0, 0, 0, 0, 0.439, 0], [0, 0, 0, 0, 0, 0.439]]) * 1e11, 'Yc': stiffness_from_youngpoisson(3, 200e9, 0.25) } }, ), 'piezo': ({ 'g': nm.array([[0, 0, 0, 0, 11.404, 0], [0, 0, 0, 0, 0, 11.404], [-4.322, -4.322, 17.360, 0, 0, 0]]) / mat_g_sc, 'd': nm.array([[1.284, 0, 0], [0, 1.284, 0], [0, 0, 1.505]]) * 1e-8 / mat_d_sc }, ), } functions = { 'match_x_plane': (per.match_x_plane, ), 'match_y_plane': (per.match_y_plane, ), 'match_z_plane': (per.match_z_plane, ), } ebcs = { 'fixed_u': ('Corners', { 'u.all': 0.0 }), 'fixed_r': ('Gamma_ms', { 'r.all': 0.0 }), 'fixed_r1_s1': ('Gamma_s1', { 'r.0': 1.0 }), 'fixed_r0_s1': ('Gamma_s1', { 'r.0': 0.0 }), 'fixed_r1_s2': ('Gamma_s2', { 'r.0': 1.0 }), 'fixed_r0_s2': ('Gamma_s2', { 'r.0': 0.0 }), } integrals = { 'i2': 2, } solvers = { 'ls_d': ('ls.scipy_direct', {}), 'ls_i': ('ls.scipy_iterative', {}), 'ns_ea6': ('nls.newton', { 'eps_a': 1e6, 'eps_r': 1e-3, }), 'ns_ea0': ('nls.newton', { 'eps_a': 1e0, 'eps_r': 1e-3, }), } coefs = { 'A1': { 'status': 'auxiliary', 'requires': ['pis_u', 'corrs_rs'], 'expression': 'dw_lin_elastic.i2.Ymc(elastic.D, U1, U2)', 'set_variables': [('U1', ('corrs_rs', 'pis_u'), 'u'), ('U2', ('corrs_rs', 'pis_u'), 'u')], 'class': cb.CoefSymSym, }, 'A2': { 'status': 'auxiliary', 'requires': ['corrs_rs'], 'expression': 'dw_diffusion.i2.Ym(piezo.d, R1, R2)', 'set_variables': [('R1', 'corrs_rs', 'r'), ('R2', 'corrs_rs', 'r')], 'class': cb.CoefSymSym, }, 'A': { 'requires': ['c.A1', 'c.A2'], 'expression': 'c.A1 + c.A2', 'class': cb.CoefEval, }, 'vol': { 'regions': ['Ym', 'Yc1', 'Yc2'], 'expression': 'ev_volume.i2.%s(svar)', 'class': cb.VolumeFractions, }, 'eps0': { 'requires': [], 'expression': '%e' % eps0, 'class': cb.CoefEval, }, 'filenames': {}, } requirements = { 'pis_u': { 'variables': ['u'], 'class': cb.ShapeDimDim, }, 'pis_r': { 'variables': ['r'], 'class': cb.ShapeDim, }, 'corrs_rs': { 'requires': ['pis_u'], 'ebcs': ['fixed_u', 'fixed_r'], 'epbcs': ['p_ux', 'p_uy', 'p_uz', 'p_rx', 'p_ry', 'p_rz'], 'equations': { 'eq1': """dw_lin_elastic.i2.Ymc(elastic.D, v, u) - dw_piezo_coupling.i2.Ym(piezo.g, v, r) = - dw_lin_elastic.i2.Ymc(elastic.D, v, Pi_u)""", 'eq2': """ - dw_piezo_coupling.i2.Ym(piezo.g, u, s) - dw_diffusion.i2.Ym(piezo.d, s, r) = dw_piezo_coupling.i2.Ym(piezo.g, Pi_u, s)""", }, 'set_variables': [('Pi_u', 'pis_u', 'u')], 'class': cb.CorrDimDim, 'save_name': 'corrs_rs', 'solvers': { 'ls': 'ls_i', 'nls': 'ns_ea6' }, }, } # define requirements and coefficients related to conductors bc_conductors = [ ['fixed_r1_s1', 'fixed_r0_s2'], # phi = 1 on S1, phi = 0 on S2 ['fixed_r1_s2', 'fixed_r0_s1'], # phi = 0 on S1, phi = 1 on S2 ] for k in range(2): sk = '%d' % k requirements.update({ 'corrs_k' + sk: { 'requires': ['pis_r'], 'ebcs': ['fixed_u'] + bc_conductors[k], 'epbcs': ['p_ux', 'p_uy', 'p_uz', 'p_rx', 'p_ry', 'p_rz'], 'equations': { 'eq1': """dw_lin_elastic.i2.Ymc(elastic.D, v, u) - dw_piezo_coupling.i2.Ym(piezo.g, v, r) = 0""", 'eq2': """ - dw_piezo_coupling.i2.Ym(piezo.g, u, s) - dw_diffusion.i2.Ym(piezo.d, s, r) = 0""" }, 'class': cb.CorrOne, 'save_name': 'corrs_k' + sk, 'solvers': { 'ls': 'ls_d', 'nls': 'ns_ea0' }, }, }) coefs.update({ 'V1_' + sk: { 'status': 'auxiliary', 'requires': ['pis_u', 'corrs_k' + sk], 'expression': 'dw_lin_elastic.i2.Ymc(elastic.D, U1, U2)', 'set_variables': [('U1', 'corrs_k' + sk, 'u'), ('U2', 'pis_u', 'u')], 'class': cb.CoefSym, }, 'V2_' + sk: { 'status': 'auxiliary', 'requires': ['pis_u', 'corrs_k' + sk], 'expression': 'dw_piezo_coupling.i2.Ym(piezo.g, U1, R1)', 'set_variables': [('R1', 'corrs_k' + sk, 'r'), ('U1', 'pis_u', 'u')], 'class': cb.CoefSym, }, 'V' + sk: { 'requires': ['c.V1_' + sk, 'c.V2_' + sk], 'expression': 'c.V1_%s - c.V2_%s' % (sk, sk), 'class': cb.CoefEval, }, }) return locals()
def define(is_opt=False): filename_mesh = data_dir + "/meshes/3d/matrix_fiber_rand.vtk" mesh = Mesh.from_file(filename_mesh) bbox = mesh.get_bounding_box() regions = {"Y": "all", "Ym": ("cells of group 7", "cell"), "Yf": ("r.Y -c r.Ym", "cell")} regions.update(define_box_regions(3, bbox[0], bbox[1])) functions = { "get_mat": (lambda ts, coors, mode=None, problem=None, **kwargs: get_mat(coors, mode, problem),), "match_x_plane": (per.match_x_plane,), "match_y_plane": (per.match_y_plane,), "match_z_plane": (per.match_z_plane,), } materials = {"mat": "get_mat"} fields = {"corrector": ("real", 3, "Y", 1)} variables = { "u": ("unknown field", "corrector"), "v": ("test field", "corrector", "u"), "Pi": ("parameter field", "corrector", "u"), "Pi1": ("parameter field", "corrector", "(set-to-None)"), "Pi2": ("parameter field", "corrector", "(set-to-None)"), } ebcs = {"fixed_u": ("Corners", {"u.all": 0.0})} epbcs = { "periodic_x": (["Left", "Right"], {"u.all": "u.all"}, "match_x_plane"), "periodic_y": (["Near", "Far"], {"u.all": "u.all"}, "match_y_plane"), "periodic_z": (["Top", "Bottom"], {"u.all": "u.all"}, "match_z_plane"), } all_periodic = ["periodic_%s" % ii for ii in ["x", "y", "z"][:3]] options = { "coefs": "coefs", "requirements": "requirements", "volume": {"variables": ["u"], "expression": "d_volume.5.Y( u )"}, "output_dir": "output", "coefs_filename": "coefs_le", } equation_corrs = { "balance_of_forces": """dw_lin_elastic.5.Y(mat.D, v, u) = - dw_lin_elastic.5.Y(mat.D, v, Pi)""" } coefs = { "D": { "requires": ["pis", "corrs_rs"], "expression": "dw_lin_elastic.5.Y(mat.D, Pi1, Pi2 )", "set_variables": [("Pi1", ("pis", "corrs_rs"), "u"), ("Pi2", ("pis", "corrs_rs"), "u")], "class": cb.CoefSymSym, }, "vol": {"regions": ["Ym", "Yf"], "expression": "d_volume.5.%s(u)", "class": cb.VolumeFractions}, "filenames": {}, } requirements = { "pis": {"variables": ["u"], "class": cb.ShapeDimDim}, "corrs_rs": { "requires": ["pis"], "ebcs": ["fixed_u"], "epbcs": all_periodic, "equations": equation_corrs, "set_variables": [("Pi", "pis", "u")], "class": cb.CorrDimDim, "save_name": "corrs_le", "dump_variables": ["u"], }, } solvers = { "ls": ("ls.scipy_direct", {}), "newton": ("nls.newton", {"i_max": 1, "eps_a": 1e-4, "problem": "linear"}), } if is_opt: options.update({"parametric_hook": "optimization_hook", "float_format": "%.16e"}) return locals()
def gen_mesh_from_goem(geo, a=None, quadratic=False, verbose=True, refine=False, polyfilename='./meshgen.poly', out='mesh', **kwargs): """ Runs mesh generator - tetgen for 3D or triangle for 2D meshes. Parameters ---------- geo : geometry geometry description a : int, optional a maximum area/volume constraint quadratic : bool, optional set True for quadratic elements verbose : bool, optional detailed information refine : bool, optional refines mesh Returns ------- mesh : Mesh instance triangular or tetrahedral mesh """ import os.path as op import pexpect # write geometry to poly file geo.to_poly_file(polyfilename) if not refine: params = "-Apq" else: params = "-Arq" if verbose: params = params + " -Q" if a != None and not refine: params = params + " -a%f" % (a) if refine: params = params + " -a" if quadratic: params = params + " -o2" params = params + " %s" % (polyfilename) meshgen_call = {2: 'triangle', 3: 'tetgen'} cmd = "%s %s" % (meshgen_call[geo.dim], params) if verbose: print "Generating mesh using", cmd if geo.dim == 2: p = pexpect.run(cmd, timeout=None) bname, ext = op.splitext(polyfilename) mesh = Mesh.from_file(bname + '.1.node') mesh.write(bname + '.' + out) if geo.dim == 3: p = pexpect.spawn(cmd, timeout=None) if not refine: p.expect("Opening %s." % (polyfilename)) else: p.expect("Opening %s.node.\r\n" % (polyfilename)) p.expect("Opening %s.ele.\r\n" % (polyfilename)) p.expect("Opening %s.face.\r\n" % (polyfilename)) p.expect("Opening %s.vol." % (polyfilename)) assert p.before == "" p.expect(pexpect.EOF) if p.before != "\r\n": print p.before raise "Error when running mesh generator (see above for output): %s" % cmd
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) * nfi * (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 define(filename_mesh=None, cg1=None, cg2=None): if filename_mesh is None: filename_mesh = osp.join(data_dir, 'macro_perf.vtk') cg1, cg2 = 0.0015, 0.0015 # y and z coordinates of center of gravity mesh = Mesh.from_file(filename_mesh) poroela_mezo_file = osp.join(data_dir, 'perf_BD2B_mes.py') material_cache['meso_filename'] = poroela_mezo_file bbox = mesh.get_bounding_box() regions = define_box_regions(mesh.dim, bbox[0], bbox[1], eps=1e-6) regions.update({ 'Omega': 'all', 'Wall': ('r.Top +v r.Bottom +v r.Far +v r.Near', 'facet'), # 'In': ('r.Left -v r.Wall', 'facet'), # 'Out': ('r.Right -v r.Wall', 'facet'), 'In': ('copy r.Left', 'facet'), 'Out': ('copy r.Right ', 'facet'), 'Out_u': ('r.Out -v (r.Top +v r.Bottom)', 'facet'), }) val_w1 = 5e3 val_w2 = 5e3 ebcs, bc_funs, mats, lcbcs = define_bc(cg1, cg2, is_steady=False, val_in=val_w1, val_out=val_w2) fields = { 'displacement': ('real', 'vector', 'Omega', 1), 'pressure': ('real', 'scalar', 'Omega', 1), 'velocity1': ('real', 'vector', 'Omega', 1), 'velocity2': ('real', 'vector', 'Omega', 1), 'sfield': ('real', "scalar", 'Omega', 1), } variables = { #Displacement 'u': ('unknown field', 'displacement'), 'v': ('test field', 'displacement', 'u'), #Pressure 'p': ('unknown field', 'pressure'), 'q': ('test field', 'pressure', 'p'), 'ls': ('unknown field', 'pressure'), 'lv': ('test field', 'pressure', 'ls'), #Velocity 'w1': ('unknown field', 'velocity1'), 'z1': ('test field', 'velocity1', 'w1'), 'w2': ('unknown field', 'velocity2'), 'z2': ('test field', 'velocity2', 'w2'), 'U': ('parameter field', 'displacement', 'u'), 'P': ('parameter field', 'pressure', 'p'), 'W1': ('parameter field', 'velocity1', 'w1'), 'W2': ('parameter field', 'velocity2', 'w2'), 'svar': ('parameter field', 'sfield', '(set-to-none)'), } state_vars = ['p', 'u', 'w1', 'w2'] functions = { 'get_homog': (lambda ts, coors, problem, mode=None, **kwargs: \ get_homog(coors,problem, mode, **kwargs),), 'get_u': (lambda ts, coor, mode=None, problem=None, **kwargs: get_u(tstep, coor),), } functions.update(bc_funs) materials = { 'hom': 'get_homog', } materials.update(mats) #Definition of integrals integrals = { 'i': 5, "is": ("s", 5), } #Definition of solvers solvers = { 'ls': ('ls.mumps', {}), 'newton': ('nls.newton', { 'i_max': 1, 'eps_a': 1e-10, 'eps_r': 1e-3, 'problem': 'nonlinear', }) } options = { 'output_dir': data_dir + '/results/macro', 'ls': 'ls', 'nls': 'newton', 'micro_filename': poroela_mezo_file, 'absolute_mesh_path': True, 'output_prefix': 'Macro:', 'matrix_hook': 'mtx_hook', } #Definition of time solver and equations for steady state and time evolution cases tstep = TimeStepper(0.0, 1.0, n_step=20) equations, phook = define_time_equations(tstep) options.update({'parametric_hook': phook}) return locals()
def save_state( self, filename, state=None, out=None, fill_value=None, post_process_hook=None, linearization=None, file_per_var=False, **kwargs ): """ Parameters ---------- file_per_var : bool or None If True, data of each variable are stored in a separate file. If None, it is set to the application option value. linearization : Struct or None The linearization configuration for higher order approximations. If its kind is 'adaptive', `file_per_var` is assumed True. """ linearization = get_default(linearization, self.linearization) if linearization.kind != "adaptive": file_per_var = get_default(file_per_var, self.file_per_var) else: file_per_var = True extend = not file_per_var if (out is None) and (state is not None): out = state.create_output_dict(fill_value=fill_value, extend=extend, linearization=linearization) if post_process_hook is not None: out = post_process_hook(out, self, state, extend=extend) if linearization.kind == "adaptive": for key, val in out.iteritems(): mesh = val.get("mesh", self.domain.mesh) aux = io.edit_filename(filename, suffix="_" + val.var_name) mesh.write(aux, io="auto", out={key: val}, float_format=self.float_format, **kwargs) if hasattr(val, "levels"): output("max. refinement per group:", val.levels) elif file_per_var: meshes = {} if self.equations is None: varnames = {} for key, val in out.iteritems(): varnames[val.var_name] = 1 varnames = varnames.keys() outvars = self.create_variables(varnames) itervars = outvars.__iter__ else: itervars = self.equations.variables.iter_state for var in itervars(): rname = var.field.region.name if meshes.has_key(rname): mesh = meshes[rname] else: mesh = Mesh.from_region( var.field.region, self.domain.mesh, localize=True, is_surface=var.is_surface ) meshes[rname] = mesh vout = {} for key, val in out.iteritems(): try: if val.var_name == var.name: vout[key] = val except AttributeError: msg = "missing var_name attribute in output!" raise ValueError(msg) aux = io.edit_filename(filename, suffix="_" + var.name) mesh.write(aux, io="auto", out=vout, float_format=self.float_format, **kwargs) else: self.domain.mesh.write(filename, io="auto", out=out, float_format=self.float_format, **kwargs)
def create_expression_output(expression, name, primary_field_name, fields, materials, variables, functions=None, mode='eval', term_mode=None, extra_args=None, verbose=True, kwargs=None, min_level=0, max_level=1, eps=1e-4): """ Create output mesh and data for the expression using the adaptive linearizer. Parameters ---------- expression : str The expression to evaluate. name : str The name of the data. primary_field_name : str The name of field that defines the element groups and polynomial spaces. fields : dict The dictionary of fields used in `variables`. materials : Materials instance The materials used in the expression. variables : Variables instance The variables used in the expression. functions : Functions instance, optional The user functions for materials etc. mode : one of 'eval', 'el_avg', 'qp' The evaluation mode - 'qp' requests the values in quadrature points, 'el_avg' element averages and 'eval' means integration over each term region. term_mode : str The term call mode - some terms support different call modes and depending on the call mode different values are returned. extra_args : dict, optional Extra arguments to be passed to terms in the expression. verbose : bool If False, reduce verbosity. kwargs : dict, optional The variables (dictionary of (variable name) : (Variable instance)) to be used in the expression. min_level : int The minimum required level of mesh refinement. max_level : int The maximum level of mesh refinement. eps : float The relative tolerance parameter of mesh adaptivity. Returns ------- out : dict The output dictionary. """ field = fields[primary_field_name] vertex_coors = field.coors[:field.n_vertex_dof, :] ps = field.poly_space gps = field.gel.poly_space vertex_conn = field.econn[:, :field.gel.n_vertex] eval_dofs = get_eval_expression(expression, fields, materials, variables, functions=functions, mode=mode, extra_args=extra_args, verbose=verbose, kwargs=kwargs) eval_coors = get_eval_coors(vertex_coors, vertex_conn, gps) (level, coors, conn, vdofs, mat_ids) = create_output(eval_dofs, eval_coors, vertex_conn.shape[0], ps, min_level=min_level, max_level=max_level, eps=eps) mesh = Mesh.from_data('linearized_mesh', coors, None, [conn], [mat_ids], field.domain.mesh.descs) out = {} out[name] = Struct(name='output_data', mode='vertex', data=vdofs, var_name=name, dofs=None, mesh=mesh, level=level) out = convert_complex_output(out) return out
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 create_expression_output( expression, name, primary_field_name, fields, materials, variables, functions=None, mode="eval", term_mode=None, extra_args=None, verbose=True, kwargs=None, min_level=0, max_level=1, eps=1e-4, ): """ Create output mesh and data for the expression using the adaptive linearizer. Parameters ---------- expression : str The expression to evaluate. name : str The name of the data. primary_field_name : str The name of field that defines the element groups and polynomial spaces. fields : dict The dictionary of fields used in `variables`. materials : Materials instance The materials used in the expression. variables : Variables instance The variables used in the expression. functions : Functions instance, optional The user functions for materials etc. mode : one of 'eval', 'el_avg', 'qp' The evaluation mode - 'qp' requests the values in quadrature points, 'el_avg' element averages and 'eval' means integration over each term region. term_mode : str The term call mode - some terms support different call modes and depending on the call mode different values are returned. extra_args : dict, optional Extra arguments to be passed to terms in the expression. verbose : bool If False, reduce verbosity. kwargs : dict, optional The variables (dictionary of (variable name) : (Variable instance)) to be used in the expression. min_level : int The minimum required level of mesh refinement. max_level : int The maximum level of mesh refinement. eps : float The relative tolerance parameter of mesh adaptivity. Returns ------- out : dict The output dictionary. """ field = fields[primary_field_name] vertex_coors = field.coors[: field.n_vertex_dof, :] coors = [] vdofs = [] conns = [] mat_ids = [] levels = [] offset = 0 for ig, ap in field.aps.iteritems(): ps = ap.interp.poly_spaces["v"] gps = ap.interp.gel.interp.poly_spaces["v"] group = field.domain.groups[ig] vertex_conn = ap.econn[:, : group.shape.n_ep] eval_dofs = get_eval_expression( expression, ig, fields, materials, variables, functions=functions, mode=mode, extra_args=extra_args, verbose=verbose, kwargs=kwargs, ) eval_coors = get_eval_coors(vertex_coors, vertex_conn, gps) (level, _coors, conn, _vdofs, _mat_ids) = create_output( eval_dofs, eval_coors, group.shape.n_el, ps, min_level=min_level, max_level=max_level, eps=eps ) _mat_ids[:] = field.domain.mesh.mat_ids[ig][0] coors.append(_coors) vdofs.append(_vdofs) conns.append(conn + offset) mat_ids.append(_mat_ids) levels.append(level) offset += _coors.shape[0] coors = nm.concatenate(coors, axis=0) vdofs = nm.concatenate(vdofs, axis=0) mesh = Mesh.from_data("linearized_mesh", coors, None, conns, mat_ids, field.domain.mesh.descs) out = {} out[name] = Struct( name="output_data", mode="vertex", data=vdofs, var_name=name, dofs=None, mesh=mesh, levels=levels ) out = convert_complex_output(out) return out
def define(filename_mesh=None): eps0 = 0.01 # given scale parameter if filename_mesh is None: filename_mesh = osp.join(data_dir, 'micro_perf_puc.vtk') mesh = Mesh.from_file(filename_mesh) dim = 3 sym = (dim + 1) * dim // 2 sym_eye = 'nm.array([1,1,0])' if dim == 2 else 'nm.array([1,1,1,0,0,0])' bbox = mesh.get_bounding_box() regions = define_box_regions(mesh.dim, bbox[0], bbox[1], eps=1e-3) regions.update({ 'Y': 'all', 'Gamma_Y': ('vertices of surface', 'facet'), # solid matrix 'Ys': 'cells of group 1', 'Ys_left': ('r.Ys *v r.Left', 'vertex'), 'Ys_right': ('r.Ys *v r.Right', 'vertex'), 'Ys_bottom': ('r.Ys *v r.Bottom', 'vertex'), 'Ys_top': ('r.Ys *v r.Top', 'vertex'), 'Gamma_Ysf': ('r.Ys *v r.Yf', 'facet', 'Ys'), # channel 'Yf': 'cells of group 2', 'Yf0': ('r.Yf -v r.Gamma_Yfs', 'vertex'), 'Yf_left': ('r.Yf0 *v r.Left', 'vertex'), 'Yf_right': ('r.Yf0 *v r.Right', 'vertex'), 'Yf_bottom': ('r.Yf0 *v r.Bottom', 'vertex'), 'Yf_top': ('r.Yf0 *v r.Top', 'vertex'), 'Gamma_Yfs': ('r.Ys *v r.Yf', 'facet', 'Yf'), }) if dim == 3: regions.update({ 'Ys_far': ('r.Ys *v r.Far', 'vertex'), 'Ys_near': ('r.Ys *v r.Near', 'vertex'), 'Yf_far': ('r.Yf0 *v r.Far', 'vertex'), 'Yf_near': ('r.Yf0 *v r.Near', 'vertex'), }) fields = { 'volume': ('real', 'scalar', 'Y', 1), 'displacement': ('real', 'vector', 'Ys', 1), 'pressure': ('real', 'scalar', 'Yf', 1), 'velocity': ('real', 'vector', 'Yf', 2), } variables = { # displacement 'u': ('unknown field', 'displacement'), 'v': ('test field', 'displacement', 'u'), 'Pi_u': ('parameter field', 'displacement', 'u'), 'U1': ('parameter field', 'displacement', '(set-to-None)'), 'U2': ('parameter field', 'displacement', '(set-to-None)'), # velocity 'w': ('unknown field', 'velocity'), 'z': ('test field', 'velocity', 'w'), 'Pi_w': ('parameter field', 'velocity', 'w'), 'W1': ('parameter field', 'velocity', '(set-to-None)'), 'W2': ('parameter field', 'velocity', '(set-to-None)'), # pressure 'p': ('unknown field', 'pressure'), 'q': ('test field', 'pressure', 'p'), # volume 'volume': ('parameter field', 'volume', '(set-to-None)'), } functions = { 'match_x_plane': (per.match_x_plane, ), 'match_y_plane': (per.match_y_plane, ), 'match_z_plane': (per.match_z_plane, ), } materials = { 'matrix': ({ 'D': stiffness_from_youngpoisson(dim, 1e3, 0.49) }, ), #Soft tissue 'fluid': ( { 'eta_p': 3.6e-3 / eps0**2, #Rescaled blood viscosity 'aux_compress': 1e-18 }, ), #Auxillary compressibility } ebcs = { 'fixed_u': ('Corners', { 'u.all': 0.0 }), 'fixed_w': ('Gamma_Yfs', { 'w.all': 0.0 }), } epbcs, periodic = get_periodic_bc([('u', 'Ys'), ('p', 'Yf'), ('w', 'Yf')]) integrals = { 'i': 4, } options = { 'coefs': 'coefs', 'coefs_filename': 'coefs_micro', 'requirements': 'requirements', 'volume': { 'variables': ['u', 'p'], 'expression': 'd_volume.i.Ys(u) + d_volume.i.Yf(p)', }, 'output_dir': data_dir + '/results/micro', 'ls': 'ls', 'file_per_var': True, 'absolute_mesh_path': True, 'multiprocessing': True, 'output_prefix': 'micro:', } #Definition of used solvers solvers = { 'ls': ('ls.mumps', {}), 'ns_em9': ('nls.newton', { 'i_max': 1, 'eps_a': 1e-9, 'eps_r': 1e-3, 'problem': 'nonlinear' }), 'ns_em12': ('nls.newton', { 'i_max': 1, 'eps_a': 1e-12, 'eps_r': 1e-3, 'problem': 'nonlinear' }), } #Definition of homogenized coefficients, see (22) and (23) coefs = { #Elasticity coefficient 'A': { 'requires': ['pis_u', 'corrs_omega_ij'], 'expression': 'dw_lin_elastic.i.Ys(matrix.D, U1, U2)', 'set_variables': [('U1', ('corrs_omega_ij', 'pis_u'), 'u'), ('U2', ('corrs_omega_ij', 'pis_u'), 'u')], 'class': cb.CoefSymSym, }, #Biot coefficient 'hat_B': { 'status': 'auxiliary', 'requires': ['corrs_omega_ij'], 'expression': '- ev_div.i.Ys(U1)', 'set_variables': [('U1', 'corrs_omega_ij', 'u')], 'class': cb.CoefSym, }, 'B': { 'requires': ['c.phi_f', 'c.hat_B'], 'expression': 'c.hat_B + c.phi_f * %s' % sym_eye, 'class': cb.CoefEval, }, 'M': { 'requires': ['corrs_omega_p'], 'expression': 'dw_lin_elastic.i.Ys(matrix.D, U1, U2)', 'set_variables': [('U1', 'corrs_omega_p', 'u'), ('U2', 'corrs_omega_p', 'u')], 'class': cb.CoefOne, }, #Permeability 'K': { 'requires': ['corrs_psi_i'], 'expression': 'dw_div_grad.i.Yf(W1, W2)', # !!! 'set_variables': [('W1', 'corrs_psi_i', 'w'), ('W2', 'corrs_psi_i', 'w')], 'class': cb.CoefDimDim, }, #Volume fraction of fluid part 'phi_f': { 'requires': ['c.vol'], 'expression': 'c.vol["fraction_Yf"]', 'class': cb.CoefEval, }, #Coefficient for storing viscosity 'eta_p': { 'expression': '%e' % materials['fluid'][0]['eta_p'], 'class': cb.CoefEval, }, #Volume fractions 'vol': { 'regions': ['Ys', 'Yf'], 'expression': 'd_volume.i.%s(volume)', 'class': cb.VolumeFractions, }, #Surface volume fractions 'surf_vol': { 'regions': ['Ys', 'Yf'], 'expression': 'd_surface.i.%s(volume)', 'class': cb.VolumeFractions, }, 'filenames': {}, } #Definition of microscopic corrector problems requirements = { #Definition of \Pi^{ij}_k 'pis_u': { 'variables': ['u'], 'class': cb.ShapeDimDim, }, #Correcotr like class returning ones 'pis_w': { 'variables': ['w'], 'class': cb.OnesDim, }, #Corrector problem related to elasticity, see (17) 'corrs_omega_ij': { 'requires': ['pis_u'], 'ebcs': ['fixed_u'], 'epbcs': periodic['per_u'], 'is_linear': True, 'equations': { 'balance_of_forces': """dw_lin_elastic.i.Ys(matrix.D, v, u) = - dw_lin_elastic.i.Ys(matrix.D, v, Pi_u)""" }, 'set_variables': [('Pi_u', 'pis_u', 'u')], 'class': cb.CorrDimDim, 'save_name': 'corrs_omega_ij', 'dump_variables': ['u'], 'solvers': {'ls': 'ls', 'nls': 'ns_em9'}, }, # Corrector problem related to elasticity, see (18) 'corrs_omega_p': { 'requires': [], 'ebcs': ['fixed_u'], 'epbcs': periodic['per_u'], 'equations': { 'balance_of_forces': """dw_lin_elastic.i.Ys(matrix.D, v, u) = -dw_surface_ltr.i.Gamma_Ysf(v)""" }, 'class': cb.CorrOne, 'save_name': 'corrs_omega_p', 'dump_variables': ['u'], 'solvers': {'ls': 'ls', 'nls': 'ns_em3'}, }, #Corrector problem related to velocity, see (19) 'corrs_psi_i': { 'requires': ['pis_w'], 'ebcs': ['fixed_w'], 'epbcs': periodic['per_w'] + periodic['per_p'], 'is_linear': True, 'equations': { 'balance_of_forces': # !!! """dw_div_grad.i.Yf(fluid.eta_p,z, w) - dw_stokes.i.Yf(z, p) = dw_volume_dot.i.Yf(z, Pi_w)""", 'incompressibility': """dw_stokes.i.Yf(w, q) + dw_volume_dot.i.Yf(fluid.aux_compress, q, p) = 0""",# }, 'set_variables': [('Pi_w', 'pis_w', 'w')], 'class': cb.CorrDim, 'save_name': 'corrs_psi_i', 'dump_variables': ['w', 'p'], 'solvers': {'ls': 'ls', 'nls': 'ns_em12'}, }, } return locals()
def define(filename_mesh=None): eta = 3.6e-3 if filename_mesh is None: filename_mesh = osp.join(data_dir, 'meso_perf_2ch_puc.vtk') # filename_mesh = osp.join(data_dir, 'perf_mic_2chbx.vtk') mesh = Mesh.from_file(filename_mesh) poroela_micro_file = osp.join(data_dir, 'perf_BD2B_mic.py') dim = 3 sym = (dim + 1) * dim // 2 sym_eye = 'nm.array([1,1,0])' if dim == 2 else 'nm.array([1,1,1,0,0,0])' bbox = mesh.get_bounding_box() regions = define_box_regions(mesh.dim, bbox[0], bbox[1], eps=1e-3) regions.update({ 'Z': 'all', 'Gamma_Z': ('vertices of surface', 'facet'), # matrix 'Zm': 'cells of group 3', 'Zm_left': ('r.Zm *v r.Left', 'vertex'), 'Zm_right': ('r.Zm *v r.Right', 'vertex'), 'Zm_bottom': ('r.Zm *v r.Bottom', 'vertex'), 'Zm_top': ('r.Zm *v r.Top', 'vertex'), "Gamma_Zm": ('(r.Zm *v r.Zc1) +v (r.Zm *v r.Zc2)', 'facet', 'Zm'), 'Gamma_Zm1': ('r.Zm *v r.Zc1', 'facet', 'Zm'), 'Gamma_Zm2': ('r.Zm *v r.Zc2', 'facet', 'Zm'), # first canal 'Zc1': 'cells of group 1', 'Zc01': ('r.Zc1 -v r.Gamma_Zc1', 'vertex'), 'Zc1_left': ('r.Zc01 *v r.Left', 'vertex'), 'Zc1_right': ('r.Zc01 *v r.Right', 'vertex'), # 'Zc1_bottom': ('r.Zc01 *v r.Bottom', 'vertex'), # 'Zc1_top': ('r.Zc01 *v r.Top', 'vertex'), 'Gamma_Zc1': ('r.Zm *v r.Zc1', 'facet', 'Zc1'), 'Center_c1': ('vertex 973', 'vertex'), # canal center # 'Center_c1': ('vertex 1200', 'vertex'), # canal center # second canal 'Zc2': 'cells of group 2', 'Zc02': ('r.Zc2 -v r.Gamma_Zc2', 'vertex'), 'Zc2_left': ('r.Zc02 *v r.Left', 'vertex'), 'Zc2_right': ('r.Zc02 *v r.Right', 'vertex'), # 'Zc2_bottom': ('r.Zc02 *v r.Bottom', 'vertex'), # 'Zc2_top': ('r.Zc02 *v r.Top', 'vertex'), 'Gamma_Zc2': ('r.Zm *v r.Zc2', 'facet', 'Zc2'), 'Center_c2': ('vertex 487', 'vertex'), # canal center # 'Center_c2': ('vertex 1254', 'vertex'), # canal center }) if dim == 3: regions.update({ 'Zm_far': ('r.Zm *v r.Far', 'vertex'), 'Zm_near': ('r.Zm *v r.Near', 'vertex'), # 'Zc1_far': ('r.Zc01 *v r.Far', 'vertex'), # 'Zc1_near': ('r.Zc01 *v r.Near', 'vertex'), # 'Zc2_far': ('r.Zc02 *v r.Far', 'vertex'), # 'Zc2_near': ('r.Zc02 *v r.Near', 'vertex'), }) fields = { 'one': ('real', 'scalar', 'Z', 1), 'displacement': ('real', 'vector', 'Zm', 1), 'pressure_m': ('real', 'scalar', 'Zm', 1), 'pressure_c1': ('real', 'scalar', 'Zc1', 1), 'displacement_c1': ('real', 'vector', 'Zc1', 1), 'velocity1': ('real', 'vector', 'Zc1', 2), 'pressure_c2': ('real', 'scalar', 'Zc2', 1), 'displacement_c2': ('real', 'vector', 'Zc2', 1), 'velocity2': ('real', 'vector', 'Zc2', 2), } variables = { # displacement 'u': ('unknown field', 'displacement', 0), 'v': ('test field', 'displacement', 'u'), 'Pi_u': ('parameter field', 'displacement', 'u'), 'U1': ('parameter field', 'displacement', '(set-to-None)'), 'U2': ('parameter field', 'displacement', '(set-to-None)'), 'uc1': ('unknown field', 'displacement_c1', 6), 'vc1': ('test field', 'displacement_c1', 'uc1'), 'uc2': ('unknown field', 'displacement_c2', 7), 'vc2': ('test field', 'displacement_c2', 'uc2'), # velocity in canal 1 'w1': ('unknown field', 'velocity1', 1), 'z1': ('test field', 'velocity1', 'w1'), 'Pi_w1': ('parameter field', 'velocity1', 'w1'), 'par1_w1': ('parameter field', 'velocity1', '(set-to-None)'), 'par2_w1': ('parameter field', 'velocity1', '(set-to-None)'), # velocity in canal 2 'w2': ('unknown field', 'velocity2', 2), 'z2': ('test field', 'velocity2', 'w2'), 'Pi_w2': ('parameter field', 'velocity2', 'w2'), 'par1_w2': ('parameter field', 'velocity2', '(set-to-None)'), 'par2_w2': ('parameter field', 'velocity2', '(set-to-None)'), # pressure 'pm': ('unknown field', 'pressure_m', 3), 'qm': ('test field', 'pressure_m', 'pm'), 'Pm1': ('parameter field', 'pressure_m', '(set-to-None)'), 'Pm2': ('parameter field', 'pressure_m', '(set-to-None)'), 'Pi_pm': ('parameter field', 'pressure_m', 'pm'), 'pc1': ('unknown field', 'pressure_c1', 4), 'qc1': ('test field', 'pressure_c1', 'pc1'), 'par1_pc1': ('parameter field', 'pressure_c1', '(set-to-None)'), 'par2_pc1': ('parameter field', 'pressure_c1', '(set-to-None)'), 'pc2': ('unknown field', 'pressure_c2', 5), 'qc2': ('test field', 'pressure_c2', 'pc2'), 'par1_pc2': ('parameter field', 'pressure_c2', '(set-to-None)'), 'par2_pc2': ('parameter field', 'pressure_c2', '(set-to-None)'), # one 'one': ('parameter field', 'one', '(set-to-None)'), } functions = { 'match_x_plane': (per.match_x_plane,), 'match_y_plane': (per.match_y_plane,), 'match_z_plane': (per.match_z_plane,), 'get_homog': (lambda ts, coors, mode=None, problem=None, **kwargs:\ get_homog(coors, mode, problem, poroela_micro_file, **kwargs),), } materials = { 'hmatrix': 'get_homog', 'fluid': ({ 'eta_c': eta * nm.eye(dim2sym(dim)), }, ), 'mat': ({ 'k1': nm.array([[1, 0, 0]]).T, 'k2': nm.array([[0, 1, 0]]).T, 'k3': nm.array([[0, 0, 1]]).T, }, ), } ebcs = { 'fixed_u': ('Corners', { 'um.all': 0.0 }), 'fixed_pm': ('Corners', { 'p.0': 0.0 }), 'fixed_w1': ('Center_c1', { 'w1.all': 0.0 }), 'fixed_w2': ('Center_c2', { 'w2.all': 0.0 }), } epbcs, periodic = get_periodic_bc([('u', 'Zm'), ('pm', 'Zm'), ('pc1', 'Zc1'), ('w1', 'Zc1'), ('pc2', 'Zc2'), ('w2', 'Zc2')]) all_periodic1 = periodic['per_w1'] + periodic['per_pc1'] all_periodic2 = periodic['per_w2'] + periodic['per_pc2'] integrals = { 'i': 4, } options = { 'coefs': 'coefs', 'coefs_filename': 'coefs_meso', 'requirements': 'requirements', 'volume': { 'variables': ['u', 'pc1', 'pc2'], 'expression': 'd_volume.i.Zm(u) + d_volume.i.Zc1(pc1)+d_volume.i.Zc2(pc2)', }, 'output_dir': data_dir + '/results/meso', 'file_per_var': True, 'save_format': 'vtk', # Global setting. 'dump_format': 'h5', # Global setting. 'absolute_mesh_path': True, 'multiprocessing': False, 'ls': 'ls', 'nls': 'ns_m15', 'output_prefix': 'Meso:', } solvers = { 'ls': ('ls.mumps', {}), 'ls_s1': ('ls.schur_mumps', { 'schur_variables': ['pc1'], 'fallback': 'ls' }), 'ls_s2': ('ls.schur_mumps', { 'schur_variables': ['pc2'], 'fallback': 'ls' }), 'ns': ('nls.newton', { 'i_max': 1, 'eps_a': 1e-14, 'eps_r': 1e-3, 'problem': 'nonlinear' }), 'ns_em15': ('nls.newton', { 'i_max': 1, 'eps_a': 1e-15, 'eps_r': 1e-3, 'problem': 'nonlinear' }), 'ns_em12': ('nls.newton', { 'i_max': 1, 'eps_a': 1e-12, 'eps_r': 1e-3, 'problem': 'nonlinear' }), 'ns_em9': ('nls.newton', { 'i_max': 1, 'eps_a': 1e-9, 'eps_r': 1e-3, 'problem': 'nonlinear' }), 'ns_em6': ('nls.newton', { 'i_max': 1, 'eps_a': 1e-4, 'eps_r': 1e-3, 'problem': 'nonlinear' }), } #Definition of homogenized coefficients, see (33)-(35) coefs = { 'A': { 'requires': ['pis_u', 'corrs_omega_ij'], 'expression': 'dw_lin_elastic.i.Zm(hmatrix.A, U1, U2)', 'set_variables': [('U1', ('corrs_omega_ij', 'pis_u'), 'u'), ('U2', ('corrs_omega_ij', 'pis_u'), 'u')], 'class': cb.CoefSymSym, }, 'B_aux1': { 'status': 'auxiliary', 'requires': ['corrs_omega_ij'], 'expression': '- dw_surface_ltr.i.Gamma_Zm(U1)', # !!! - 'set_variables': [('U1', 'corrs_omega_ij', 'u')], 'class': cb.CoefSym, }, 'B_aux2': { 'status': 'auxiliary', 'requires': ['corrs_omega_ij', 'pis_u', 'corr_one'], 'expression': 'dw_biot.i.Zm(hmatrix.B, U1, one)', 'set_variables': [('U1', ('corrs_omega_ij', 'pis_u'), 'u'), ('one', 'corr_one', 'one')], 'class': cb.CoefSym, }, 'B': { 'requires': ['c.B_aux1', 'c.B_aux2', 'c.vol_c'], 'expression': 'c.B_aux1 + c.B_aux2 + c.vol_c* %s' % sym_eye, 'class': cb.CoefEval, }, 'H11': { 'requires': ['corrs_phi_k_1'], 'expression': 'dw_diffusion.i.Zm(hmatrix.K, Pm1, Pm2)', 'set_variables': [('Pm1', 'corrs_phi_k_1', 'pm'), ('Pm2', 'corrs_phi_k_1', 'pm')], 'class': cb.CoefDimDim, }, 'H12': { 'requires': ['corrs_phi_k_1', 'corrs_phi_k_2'], 'expression': 'dw_diffusion.i.Zm(hmatrix.K, Pm1, Pm2)', 'set_variables': [('Pm1', 'corrs_phi_k_1', 'pm'), ('Pm2', 'corrs_phi_k_2', 'pm')], 'class': cb.CoefDimDim, }, 'H21': { 'requires': ['corrs_phi_k_1', 'corrs_phi_k_2'], 'expression': 'dw_diffusion.i.Zm(hmatrix.K, Pm1, Pm2)', 'set_variables': [('Pm1', 'corrs_phi_k_2', 'pm'), ('Pm2', 'corrs_phi_k_1', 'pm')], 'class': cb.CoefDimDim, }, 'H22': { 'requires': ['corrs_phi_k_2'], 'expression': 'dw_diffusion.i.Zm(hmatrix.K, Pm1, Pm2)', 'set_variables': [('Pm1', 'corrs_phi_k_2', 'pm'), ('Pm2', 'corrs_phi_k_2', 'pm')], 'class': cb.CoefDimDim, }, 'K': { 'requires': ['corrs_pi_k', 'pis_pm'], 'expression': 'dw_diffusion.i.Zm(hmatrix.K, Pm1, Pm2)', 'set_variables': [('Pm1', ('corrs_pi_k', 'pis_pm'), 'pm'), ('Pm2', ('corrs_pi_k', 'pis_pm'), 'pm')], 'class': cb.CoefDimDim, }, 'Q1': { 'requires': ['corrs_phi_k_1', 'pis_pm'], 'expression': 'dw_diffusion.i.Zm(hmatrix.K, Pm1, Pm2)', 'set_variables': [('Pm1', 'pis_pm', 'pm'), ('Pm2', 'corrs_phi_k_1', 'pm')], 'class': cb.CoefDimDim, }, 'P1': { 'requires': ['c.Q1', 'c.vol'], 'expression': 'c.vol["fraction_Zc1"] * nm.eye(%d) - c.Q1' % dim, 'class': cb.CoefEval, }, 'P1T': { 'requires': ['c.P1'], 'expression': 'c.P1.T', 'class': cb.CoefEval, }, 'Q2': { 'requires': ['corrs_phi_k_2', 'pis_pm'], 'expression': 'dw_diffusion.i.Zm(hmatrix.K, Pm1, Pm2)', 'set_variables': [('Pm1', 'pis_pm', 'pm'), ('Pm2', 'corrs_phi_k_2', 'pm')], 'class': cb.CoefDimDim, }, 'P2': { 'requires': ['c.Q2', 'c.vol'], 'expression': 'c.vol["fraction_Zc2"] * nm.eye(%d) - c.Q2' % dim, 'class': cb.CoefEval, }, 'P2T': { 'requires': ['c.P2'], 'expression': 'c.P2.T', 'class': cb.CoefEval, }, 'M_aux1': { 'status': 'auxiliary', 'requires': [], 'expression': 'ev_volume_integrate_mat.i.Zm(hmatrix.M, one)', 'set_variables': [], 'class': cb.CoefOne, }, 'M_aux2': { 'status': 'auxiliary', 'requires': ['corrs_omega_p', 'corr_one'], 'expression': 'dw_biot.i.Zm(hmatrix.B, U1, one)', 'set_variables': [('U1', 'corrs_omega_p', 'u'), ('one', 'corr_one', 'one')], 'class': cb.CoefOne, }, 'M_aux3': { 'status': 'auxiliary', 'requires': ['corrs_omega_p'], 'expression': ' dw_surface_ltr.i.Gamma_Zm(U1)', 'set_variables': [('U1', 'corrs_omega_p', 'u')], 'class': cb.CoefOne, }, 'M': { 'requires': ['c.M_aux1', 'c.M_aux2', 'c.M_aux3'], 'expression': 'c.M_aux1 + c.M_aux2 -c.M_aux3 ', 'class': cb.CoefEval, }, 'S1': { 'requires': ['corrs_psi_ij_1', 'pis_w1'], 'expression': 'dw_lin_elastic.i.Zc1(fluid.eta_c, par1_w1, par2_w1)', 'set_variables': [('par1_w1', ('corrs_psi_ij_1', 'pis_w1'), 'w1'), ('par2_w1', ('corrs_psi_ij_1', 'pis_w1'), 'w1')], 'class': cb.CoefSymSym, }, 'S2': { 'requires': ['corrs_psi_ij_2', 'pis_w2'], 'expression': 'dw_lin_elastic.i.Zc2(fluid.eta_c, par1_w2, par2_w2)', 'set_variables': [('par1_w2', ('corrs_psi_ij_2', 'pis_w2'), 'w2'), ('par2_w2', ('corrs_psi_ij_2', 'pis_w2'), 'w2')], 'class': cb.CoefSymSym, }, 'vol': { 'regions': ['Zm', 'Zc1', 'Zc2'], 'expression': 'd_volume.i.%s(one)', 'class': cb.VolumeFractions, }, 'surf_vol': { 'regions': ['Zm', 'Zc1', 'Zc2'], 'expression': 'd_surface.i.%s(one)', 'class': cb.VolumeFractions, }, 'surf_c': { 'requires': ['c.surf_vol'], 'expression': 'c.surf_vol["fraction_Zc1"]+c.surf_vol["fraction_Zc2"]', 'class': cb.CoefEval, }, 'vol_c': { 'requires': ['c.vol'], 'expression': 'c.vol["fraction_Zc1"]+c.vol["fraction_Zc2"]', 'class': cb.CoefEval, }, 'filenames': {}, } #Definition of mesoscopic corrector problems requirements = { 'corr_one': { 'variable': 'one', 'expression': "nm.ones((problem.fields['one'].n_vertex_dof, 1), dtype=nm.float64)", 'class': cb.CorrEval, }, 'pis_u': { 'variables': ['u'], 'class': cb.ShapeDimDim, 'save_name': 'corrs_pis_u', 'dump_variables': ['u'], }, 'pis_pm': { 'variables': ['pm'], 'class': cb.ShapeDim, }, 'pis_w1': { 'variables': ['w1'], 'class': cb.ShapeDimDim, }, 'pis_w2': { 'variables': ['w2'], 'class': cb.ShapeDimDim, }, # Corrector problem, see (31)_1 'corrs_omega_ij': { 'requires': ['pis_u'], 'ebcs': ['fixed_u'], 'epbcs': periodic['per_u'], 'is_linear': True, 'equations': { 'balance_of_forces': """dw_lin_elastic.i.Zm(hmatrix.A, v, u) = - dw_lin_elastic.i.Zm(hmatrix.A, v, Pi_u)""" }, 'set_variables': [('Pi_u', 'pis_u', 'u')], 'class': cb.CorrDimDim, 'save_name': 'corrs_omega_ij', 'dump_variables': ['u'], 'solvers': { 'ls': 'ls', 'nls': 'ns_em6' }, 'is_linear': True, }, # Corrector problem, see (31)_2 'corrs_omega_p': { 'requires': ['corr_one'], 'ebcs': ['fixed_u'], 'epbcs': periodic['per_u'], 'equations': { 'balance_of_forces': """dw_lin_elastic.i.Zm(hmatrix.A, v, u) = dw_biot.i.Zm(hmatrix.B, v, one) - dw_surface_ltr.i.Gamma_Zm(v)""", }, 'set_variables': [('one', 'corr_one', 'one')], 'class': cb.CorrOne, 'save_name': 'corrs_omega_p', 'dump_variables': ['u'], 'solvers': { 'ls': 'ls', 'nls': 'ns_em9' }, }, # Corrector problem, see (31)_3 'corrs_pi_k': { 'requires': ['pis_pm'], 'ebcs': [], # ['fixed_pm'], 'epbcs': periodic['per_pm'], 'is_linear': True, 'equations': { 'eq': """dw_diffusion.i.Zm(hmatrix.K, qm, pm) = - dw_diffusion.i.Zm(hmatrix.K, qm, Pi_pm)""", }, 'set_variables': [('Pi_pm', 'pis_pm', 'pm')], 'class': cb.CorrDim, 'save_name': 'corrs_pi_k', 'dump_variables': ['pm'], 'solvers': { 'ls': 'ls', 'nls': 'ns_em12' }, }, # Corrector problem, see (31)_4 'corrs_phi_k_1': { 'requires': [], 'ebcs': [], 'epbcs': periodic['per_pm'], 'equations': { 'eq': """dw_diffusion.i.Zm(hmatrix.K, qm, pm) = - dw_surface_ndot.i.Gamma_Zm1(mat.k%d, qm)""", }, 'class': cb.CorrEqPar, 'eq_pars': [(ii + 1) for ii in range(dim)], 'save_name': 'corrs_phi_k_1', 'dump_variables': ['pm'], 'solvers': { 'ls': 'ls', 'nls': 'ns_em9' }, }, 'corrs_phi_k_2': { 'requires': [], 'ebcs': [], 'epbcs': periodic['per_pm'], 'equations': { 'eq': """dw_diffusion.i.Zm(hmatrix.K, qm, pm) = - dw_surface_ndot.i.Gamma_Zm2(mat.k%d, qm)""", }, 'class': cb.CorrEqPar, 'eq_pars': [(ii + 1) for ii in range(dim)], 'save_name': 'corrs_phi_k_2', 'dump_variables': ['pm'], 'solvers': { 'ls': 'ls', 'nls': 'ns_em9' }, }, # Corrector problem, see (32) 'corrs_psi_ij_1': { 'requires': ['pis_w1'], 'ebcs': ['fixed_w1'], 'epbcs': periodic['per_w1'] + periodic['per_pc1'], 'equations': { 'eq1': """2*dw_lin_elastic.i.Zc1(fluid.eta_c, z1, w1) - dw_stokes.i.Zc1(z1, pc1) = - 2*dw_lin_elastic.i.Zc1(fluid.eta_c, z1, Pi_w1)""", 'eq2': """dw_stokes.i.Zc1(w1, qc1) = - dw_stokes.i.Zc1(Pi_w1, qc1)""" }, 'set_variables': [('Pi_w1', 'pis_w1', 'w1')], 'class': cb.CorrDimDim, 'save_name': 'corrs_psi_ij_1', 'dump_variables': ['w1', 'pc1'], 'solvers': { 'ls': 'ls', 'nls': 'ns_em15' }, # 'solvers': {'ls': 'ls_s1', 'nls': 'ns_em15'}, 'is_linear': True, }, 'corrs_psi_ij_2': { 'requires': ['pis_w2'], 'ebcs': ['fixed_w2'], 'epbcs': periodic['per_w2'] + periodic['per_pc2'], 'equations': { 'eq1': """2*dw_lin_elastic.i.Zc2(fluid.eta_c, z2, w2) - dw_stokes.i.Zc2(z2, pc2) = - 2*dw_lin_elastic.i.Zc2(fluid.eta_c, z2, Pi_w2)""", 'eq2': """dw_stokes.i.Zc2(w2, qc2) = - dw_stokes.i.Zc2(Pi_w2, qc2)""" }, 'set_variables': [('Pi_w2', 'pis_w2', 'w2')], 'class': cb.CorrDimDim, 'save_name': 'corrs_psi_ij_1', 'dump_variables': ['w2', 'pc2'], 'solvers': { 'ls': 'ls', 'nls': 'ns_em15' }, # 'solvers': {'ls': 'ls_s2', 'nls': 'ns_em15'}, 'is_linear': True, }, } return locals()
def gen_mesh_from_voxels(voxels, dims, etype='q'): """ Generate FE mesh from voxels (volumetric data). Parameters ---------- voxels : array Voxel matrix, 1=material. dims : array Size of one voxel. etype : integer, optional 'q' - quadrilateral or hexahedral elements 't' - triangular or tetrahedral elements Returns ------- mesh : Mesh instance Finite element mesh. """ dims = dims.squeeze() dim = len(dims) nddims = nm.array(voxels.shape) + 2 nodemtx = nm.zeros(nddims, dtype=nm.int32) if dim == 2: #iy, ix = nm.where(voxels.transpose()) iy, ix = nm.where(voxels) nel = ix.shape[0] if etype == 'q': nodemtx[ix,iy] += 1 nodemtx[ix + 1,iy] += 1 nodemtx[ix + 1,iy + 1] += 1 nodemtx[ix,iy + 1] += 1 elif etype == 't': nodemtx[ix,iy] += 2 nodemtx[ix + 1,iy] += 1 nodemtx[ix + 1,iy + 1] += 2 nodemtx[ix,iy + 1] += 1 nel *= 2 elif dim == 3: #iy, ix, iz = nm.where(voxels.transpose(1, 0, 2)) iy, ix, iz = nm.where(voxels) nel = ix.shape[0] if etype == 'q': nodemtx[ix,iy,iz] += 1 nodemtx[ix + 1,iy,iz] += 1 nodemtx[ix + 1,iy + 1,iz] += 1 nodemtx[ix,iy + 1,iz] += 1 nodemtx[ix,iy,iz + 1] += 1 nodemtx[ix + 1,iy,iz + 1] += 1 nodemtx[ix + 1,iy + 1,iz + 1] += 1 nodemtx[ix,iy + 1,iz + 1] += 1 elif etype == 't': nodemtx[ix,iy,iz] += 6 nodemtx[ix + 1,iy,iz] += 2 nodemtx[ix + 1,iy + 1,iz] += 2 nodemtx[ix,iy + 1,iz] += 2 nodemtx[ix,iy,iz + 1] += 2 nodemtx[ix + 1,iy,iz + 1] += 2 nodemtx[ix + 1,iy + 1,iz + 1] += 6 nodemtx[ix,iy + 1,iz + 1] += 2 nel *= 6 else: msg = 'incorrect voxel dimension! (%d)' % dim raise ValueError(msg) ndidx = nm.where(nodemtx) coors = nm.array(ndidx).transpose() * dims nnod = coors.shape[0] nodeid = -nm.ones(nddims, dtype=nm.int32) nodeid[ndidx] = nm.arange(nnod) # generate elements if dim == 2: elems = nm.array([nodeid[ix,iy], nodeid[ix + 1,iy], nodeid[ix + 1,iy + 1], nodeid[ix,iy + 1]]).transpose() elif dim == 3: elems = nm.array([nodeid[ix,iy,iz], nodeid[ix + 1,iy,iz], nodeid[ix + 1,iy + 1,iz], nodeid[ix,iy + 1,iz], nodeid[ix,iy,iz + 1], nodeid[ix + 1,iy,iz + 1], nodeid[ix + 1,iy + 1,iz + 1], nodeid[ix,iy + 1,iz + 1]]).transpose() if etype == 't': elems = elems_q2t(elems) eid = etype + str(dim) eltab = {'q2': 4, 'q3': 8, 't2': 3, 't3': 4} mesh = Mesh.from_data('voxel_data', coors, nm.ones((nnod,), dtype=nm.int32), {0: nm.ascontiguousarray(elems)}, {0: nm.ones((nel,), dtype=nm.int32)}, {0: '%d_%d' % (dim, eltab[eid])}) return mesh
def extract_time_history(filename, extract, verbose=True): """Extract time history of a variable from a multi-time-step results file. Parameters ---------- filename : str The name of file to extract from. extract : str The description of what to extract in a string of comma-separated description items. A description item consists of: name of the variable to extract, mode ('e' for elements, 'n' for nodes), ids of the nodes or elements (given by the mode). Example: 'u n 10 15, p e 0' means variable 'u' in nodes 10, 15 and variable 'p' in element 0. verbose : bool Verbosity control. Returns ------- ths : dict The time histories in a dict with variable names as keys. If a nodal variable is requested in elements, its value is a dict of histories in the element nodes. ts : TimeStepper instance The time stepping information. """ output('extracting selected data...', verbose=verbose) output('selection:', extract, verbose=verbose) ## # Parse extractions. pes = OneTypeList(Struct) for chunk in extract.split(','): aux = chunk.strip().split() pes.append(Struct(var = aux[0], mode = aux[1], indx = map(int, aux[2:]), igs = None)) ## # Verify array limits, set igs for element data, shift indx. mesh = Mesh.from_file(filename) n_el, n_els, offs = mesh.n_el, mesh.n_els, mesh.el_offsets for pe in pes: if pe.mode == 'n': for ii in pe.indx: if (ii < 0) or (ii >= mesh.n_nod): raise ValueError('node index 0 <= %d < %d!' % (ii, mesh.n_nod)) if pe.mode == 'e': pe.igs = [] for ii, ie in enumerate(pe.indx[:]): if (ie < 0) or (ie >= n_el): raise ValueError('element index 0 <= %d < %d!' % (ie, n_el)) ig = (ie < n_els).argmax() pe.igs.append(ig) pe.indx[ii] = ie - offs[ig] ## print pes ## # Extract data. # Assumes only one element group (ignores igs)! io = MeshIO.any_from_filename(filename) ths = {} for pe in pes: mode, nname = io.read_data_header(pe.var) output(mode, nname, verbose=verbose) if ((pe.mode == 'n' and mode == 'vertex') or (pe.mode == 'e' and mode == 'cell')): th = io.read_time_history(nname, pe.indx) elif pe.mode == 'e' and mode == 'vertex': conn = mesh.conns[0] th = {} for iel in pe.indx: ips = conn[iel] th[iel] = io.read_time_history(nname, ips) else: raise ValueError('cannot extract cell data %s in nodes!' % pe.var) ths[pe.var] = th output('...done', verbose=verbose) ts = TimeStepper(*io.read_time_stepper()) return ths, ts
def create_expression_output(expression, name, primary_field_name, fields, materials, variables, functions=None, mode='eval', term_mode=None, extra_args=None, verbose=True, kwargs=None, min_level=0, max_level=1, eps=1e-4): """ Create output mesh and data for the expression using the adaptive linearizer. Parameters ---------- expression : str The expression to evaluate. name : str The name of the data. primary_field_name : str The name of field that defines the element groups and polynomial spaces. fields : dict The dictionary of fields used in `variables`. materials : Materials instance The materials used in the expression. variables : Variables instance The variables used in the expression. functions : Functions instance, optional The user functions for materials etc. mode : one of 'eval', 'el_avg', 'qp' The evaluation mode - 'qp' requests the values in quadrature points, 'el_avg' element averages and 'eval' means integration over each term region. term_mode : str The term call mode - some terms support different call modes and depending on the call mode different values are returned. extra_args : dict, optional Extra arguments to be passed to terms in the expression. verbose : bool If False, reduce verbosity. kwargs : dict, optional The variables (dictionary of (variable name) : (Variable instance)) to be used in the expression. min_level : int The minimum required level of mesh refinement. max_level : int The maximum level of mesh refinement. eps : float The relative tolerance parameter of mesh adaptivity. Returns ------- out : dict The output dictionary. """ field = fields[primary_field_name] vertex_coors = field.coors[:field.n_vertex_dof, :] coors = [] vdofs = [] conns = [] mat_ids = [] levels = [] offset = 0 for ig, ap in field.aps.iteritems(): ps = ap.interp.poly_spaces['v'] gps = ap.interp.gel.interp.poly_spaces['v'] group = field.domain.groups[ig] vertex_conn = ap.econn[:, :group.shape.n_ep] eval_dofs = get_eval_expression(expression, ig, fields, materials, variables, functions=functions, mode=mode, extra_args=extra_args, verbose=verbose, kwargs=kwargs) eval_coors = get_eval_coors(vertex_coors, vertex_conn, gps) (level, _coors, conn, _vdofs, _mat_ids) = create_output(eval_dofs, eval_coors, group.shape.n_el, ps, min_level=min_level, max_level=max_level, eps=eps) _mat_ids[:] = field.domain.mesh.mat_ids[ig][0] coors.append(_coors) vdofs.append(_vdofs) conns.append(conn + offset) mat_ids.append(_mat_ids) levels.append(level) offset += _coors.shape[0] coors = nm.concatenate(coors, axis=0) vdofs = nm.concatenate(vdofs, axis=0) mesh = Mesh.from_data('linearized_mesh', coors, None, conns, mat_ids, field.domain.mesh.descs) out = {} out[name] = Struct(name='output_data', mode='vertex', data=vdofs, var_name=name, dofs=None, mesh=mesh, levels=levels) out = convert_complex_output(out) return out
def dump_to_vtk(filename, output_filename_trunk=None, step0=0, steps=None, fields=None, linearization=None): """Dump a multi-time-step results file into a sequence of VTK files.""" def _save_step(suffix, out, mesh): if linearization is not None: output('linearizing...') out = _linearize(out, fields, linearization) output('...done') for key, val in out.iteritems(): lmesh = val.get('mesh', mesh) lmesh.write(output_filename_trunk + '_' + key + suffix, io='auto', out={key : val}) if hasattr(val, 'levels'): output('max. refinement per group:', val.levels) else: mesh.write(output_filename_trunk + suffix, io='auto', out=out) output('dumping to VTK...') io = MeshIO.any_from_filename(filename) mesh = Mesh.from_file(filename, io=io) if output_filename_trunk is None: output_filename_trunk = get_trunk(filename) try: ts = TimeStepper(*io.read_time_stepper()) all_steps, times, nts, dts = extract_times(filename) except ValueError: output('no time stepping info found, assuming single step') out = io.read_data(0) if out is not None: _save_step('.vtk', out, mesh) ret = None else: ts.times = times ts.n_step = times.shape[0] if steps is None: ii0 = nm.searchsorted(all_steps, step0) iterator = ((all_steps[ii], times[ii]) for ii in xrange(ii0, len(times))) else: iterator = [(step, ts.times[step]) for step in steps] max_step = all_steps.max() for step, time in iterator: output(ts.format % (step, max_step)) out = io.read_data(step) if out is None: break _save_step('.' + ts.suffix % step + '.vtk', out, mesh) ret = ts.suffix output('...done') return ret
def main(): parser = OptionParser(usage=usage, version='%prog ' + sfepy.__version__) parser.add_option('-c', '--conf', metavar='"key : value, ..."', action='store', dest='conf', type='string', default=None, help= help['conf']) parser.add_option('-O', '--options', metavar='"key : value, ..."', action='store', dest='app_options', type='string', default=None, help=help['options']) parser.add_option('-o', '', metavar='filename', action='store', dest='output_filename_trunk', default=None, help=help['filename']) parser.add_option('--create-mesh', action='store_true', dest='create_mesh', default=False, help=help['create_mesh']) parser.add_option('--2d', action='store_true', dest='dim2', default=False, help=help['dim']) parser.add_option('-m', '--mesh', metavar='filename', action='store', dest='mesh', default=None, help=help['mesh']) parser.add_option('--mesh-dir', metavar='dirname', action='store', dest='mesh_dir', default='tmp', help=help['mesh_dir']) parser.add_option('--oscillator', action='store_true', dest='oscillator', default=False, help=help['oscillator']) parser.add_option('--well', action='store_true', dest='well', default=False, help=help['well']) parser.add_option('--hydrogen', action='store_true', dest='hydrogen', default=False, help=help['hydrogen']) parser.add_option('--boron', action='store_true', dest='boron', default=False, help=help['boron']) options, args = parser.parse_args() if options.create_mesh and options.mesh: output('--create-mesh and --mesh options are mutually exclusive!') return if len(args) == 1: filename_in = args[0]; auto_mesh_name = False elif len(args) == 0: auto_mesh_name = True mesh_filename = os.path.join(options.mesh_dir, 'mesh.vtk') ensure_path(mesh_filename) if options.oscillator: filename_in = fix_path("examples/quantum/oscillator.py") elif options.well: filename_in = fix_path("examples/quantum/well.py") elif options.hydrogen: filename_in = fix_path("examples/quantum/hydrogen.py") elif options.boron: filename_in = fix_path("examples/quantum/boron.py") elif options.create_mesh: output('generating mesh...') try: os.makedirs("tmp") except OSError, e: if e.errno != 17: # [Errno 17] File exists raise if options.dim2: output("dimension: 2") gp = fix_path('meshes/quantum/square.geo') os.system("cp %s tmp/mesh.geo" % gp) os.system("gmsh -2 tmp/mesh.geo -format mesh") mtv = fix_path('script/convert_mesh.py') os.system("%s tmp/mesh.mesh %s" % (mtv, mesh_filename)) else: output("dimension: 3") import sfepy.mesh as geom from sfepy.discrete.fem.mesh import Mesh try: from site_cfg import tetgen_path except ImportError: tetgen_path = '/usr/bin/tetgen' gp = fix_path('meshes/quantum/box.geo') os.system("gmsh -0 %s -o tmp/x.geo" % gp) g = geom.read_gmsh("tmp/x.geo") g.printinfo() geom.write_tetgen(g, "tmp/t.poly") geom.runtetgen("tmp/t.poly", a=0.03, Q=1.0, quadratic=False, tetgenpath=tetgen_path) m = Mesh.from_file("tmp/t.1.node") m.write(mesh_filename, io="auto") output("...mesh written to %s" % mesh_filename) return else: parser.print_help() return
def define(is_opt=False): filename_mesh = data_dir + '/meshes/3d/matrix_fiber_rand.vtk' mesh = Mesh.from_file(filename_mesh) bbox = mesh.get_bounding_box() regions = { 'Y': 'all', 'Ym': ('cells of group 7', 'cell'), 'Yf': ('r.Y -c r.Ym', 'cell'), } regions.update(define_box_regions(3, bbox[0], bbox[1])) functions = { 'get_mat': (lambda ts, coors, mode=None, problem=None, **kwargs: get_mat( coors, mode, problem), ), 'match_x_plane': (per.match_x_plane, ), 'match_y_plane': (per.match_y_plane, ), 'match_z_plane': (per.match_z_plane, ), } materials = { 'mat': 'get_mat', } fields = { 'corrector': ('real', 3, 'Y', 1), } variables = { 'u': ('unknown field', 'corrector'), 'v': ('test field', 'corrector', 'u'), 'Pi': ('parameter field', 'corrector', 'u'), 'Pi1': ('parameter field', 'corrector', '(set-to-None)'), 'Pi2': ('parameter field', 'corrector', '(set-to-None)'), } ebcs = { 'fixed_u': ('Corners', { 'u.all': 0.0 }), } epbcs = { 'periodic_x': (['Left', 'Right'], { 'u.all': 'u.all' }, 'match_x_plane'), 'periodic_y': (['Near', 'Far'], { 'u.all': 'u.all' }, 'match_y_plane'), 'periodic_z': (['Top', 'Bottom'], { 'u.all': 'u.all' }, 'match_z_plane'), } all_periodic = ['periodic_%s' % ii for ii in ['x', 'y', 'z'][:3]] options = { 'coefs': 'coefs', 'requirements': 'requirements', 'volume': { 'variables': ['u'], 'expression': 'ev_volume.5.Y( u )' }, 'output_dir': 'output', 'coefs_filename': 'coefs_le', } equation_corrs = { 'balance_of_forces': """dw_lin_elastic.5.Y(mat.D, v, u) = - dw_lin_elastic.5.Y(mat.D, v, Pi)""" } coefs = { 'D': { 'requires': ['pis', 'corrs_rs'], 'expression': 'dw_lin_elastic.5.Y(mat.D, Pi1, Pi2 )', 'set_variables': [('Pi1', ('pis', 'corrs_rs'), 'u'), ('Pi2', ('pis', 'corrs_rs'), 'u')], 'class': cb.CoefSymSym, }, 'vol': { 'regions': ['Ym', 'Yf'], 'expression': 'ev_volume.5.%s(u)', 'class': cb.VolumeFractions, }, 'filenames': {}, } requirements = { 'pis': { 'variables': ['u'], 'class': cb.ShapeDimDim, }, 'corrs_rs': { 'requires': ['pis'], 'ebcs': ['fixed_u'], 'epbcs': all_periodic, 'equations': equation_corrs, 'set_variables': [('Pi', 'pis', 'u')], 'class': cb.CorrDimDim, 'save_name': 'corrs_le', }, } solvers = { 'ls': ('ls.scipy_direct', {}), 'newton': ('nls.newton', { 'i_max': 1, 'eps_a': 1e-4, 'problem': 'linear', }) } if is_opt: options.update({ 'parametric_hook': 'optimization_hook', 'float_format': '%.16e', }) return locals()
def gen_tiled_mesh(mesh, grid=None, scale=1.0, eps=1e-6, ret_ndmap=False): """ Generate a new mesh by repeating a given periodic element along each axis. Parameters ---------- mesh : Mesh instance The input periodic FE mesh. grid : array Number of repetition along each axis. scale : float, optional Scaling factor. eps : float, optional Tolerance for boundary detection. ret_ndmap : bool, optional If True, return global node map. Returns ------- mesh_out : Mesh instance FE mesh. ndmap : array Maps: actual node id --> node id in the reference cell. """ bbox = mesh.get_bounding_box() if grid is None: iscale = max(int(1.0 / scale), 1) grid = [iscale] * mesh.dim conn = mesh.get_conn(mesh.descs[0]) mat_ids = mesh.cmesh.cell_groups coors = mesh.coors ngrps = mesh.cmesh.vertex_groups nrep = nm.prod(grid) ndmap = None output('repeating %s ...' % grid) nblk = 1 for ii, gr in enumerate(grid): if ret_ndmap: (conn, coors, ngrps, ndmap0) = tiled_mesh1d(conn, coors, ngrps, ii, gr, bbox.transpose()[ii], eps=eps, ndmap=ndmap) ndmap = ndmap0 else: conn, coors, ngrps = tiled_mesh1d(conn, coors, ngrps, ii, gr, bbox.transpose()[ii], eps=eps) nblk *= gr output('...done') mat_ids = nm.tile(mat_ids, (nrep,)) mesh_out = Mesh.from_data('tiled mesh', coors * scale, ngrps, [conn], [mat_ids], [mesh.descs[0]]) if ret_ndmap: return mesh_out, ndmap else: return mesh_out
def define(is_opt=False): filename_mesh = data_dir + '/meshes/3d/matrix_fiber_rand.vtk' mesh = Mesh.from_file(filename_mesh) bbox = mesh.get_bounding_box() regions = { 'Y' : 'all', 'Ym' : ('cells of group 7', 'cell'), 'Yf' : ('r.Y -c r.Ym', 'cell'), } regions.update(define_box_regions(3, bbox[0], bbox[1])) functions = { 'get_mat': (lambda ts, coors, mode=None, problem=None, **kwargs: get_mat(coors, mode, problem),), 'match_x_plane' : (per.match_x_plane,), 'match_y_plane' : (per.match_y_plane,), 'match_z_plane' : (per.match_z_plane,), } materials = { 'mat': 'get_mat', } fields = { 'corrector' : ('real', 3, 'Y', 1), } variables = { 'u': ('unknown field', 'corrector'), 'v': ('test field', 'corrector', 'u'), 'Pi': ('parameter field', 'corrector', 'u'), 'Pi1': ('parameter field', 'corrector', '(set-to-None)'), 'Pi2': ('parameter field', 'corrector', '(set-to-None)'), } ebcs = { 'fixed_u' : ('Corners', {'u.all' : 0.0}), } epbcs = { 'periodic_x' : (['Left', 'Right'], {'u.all' : 'u.all'}, 'match_x_plane'), 'periodic_y' : (['Near', 'Far'], {'u.all' : 'u.all'}, 'match_y_plane'), 'periodic_z' : (['Top', 'Bottom'], {'u.all' : 'u.all'}, 'match_z_plane'), } all_periodic = ['periodic_%s' % ii for ii in ['x', 'y', 'z'][:3]] options = { 'coefs': 'coefs', 'requirements': 'requirements', 'volume': { 'variables' : ['u'], 'expression' : 'd_volume.5.Y( u )' }, 'output_dir': 'output', 'coefs_filename': 'coefs_le', } equation_corrs = { 'balance_of_forces': """dw_lin_elastic.5.Y(mat.D, v, u) = - dw_lin_elastic.5.Y(mat.D, v, Pi)""" } coefs = { 'D' : { 'requires' : ['pis', 'corrs_rs'], 'expression' : 'dw_lin_elastic.5.Y(mat.D, Pi1, Pi2 )', 'set_variables': [('Pi1', ('pis', 'corrs_rs'), 'u'), ('Pi2', ('pis', 'corrs_rs'), 'u')], 'class' : cb.CoefSymSym, }, 'vol': { 'regions': ['Ym', 'Yf'], 'expression': 'd_volume.5.%s(u)', 'class': cb.VolumeFractions, }, 'filenames' : {}, } requirements = { 'pis' : { 'variables' : ['u'], 'class' : cb.ShapeDimDim, }, 'corrs_rs' : { 'requires' : ['pis'], 'ebcs' : ['fixed_u'], 'epbcs' : all_periodic, 'equations' : equation_corrs, 'set_variables' : [('Pi', 'pis', 'u')], 'class' : cb.CorrDimDim, 'save_name' : 'corrs_le', }, } solvers = { 'ls' : ('ls.scipy_direct', {}), 'newton' : ('nls.newton', { 'i_max' : 1, 'eps_a' : 1e-4, 'problem': 'linear', }) } if is_opt: options.update({ 'parametric_hook': 'optimization_hook', 'float_format': '%.16e', }) return locals()
def load_1D_vtks(fold, name): """Reads series of .vtk files and crunches them into form suitable for plot10_DG_sol. Attempts to read modal cell data for variable mod_data. i.e. ``?_modal{i}``, where i is number of modal DOF Resulting solution data have shape: ``(order, nspace_steps, ntime_steps, 1)`` Parameters ---------- fold : folder where to look for files name : used in ``{name}.i.vtk, i = 0,1, ... tns - 1`` Returns ------- coors : ndarray mod_data : ndarray solution data """ files = glob(pjoin(fold, name) + ".[0-9]*") if len(files) == 0: # no multiple time steps, try loading single file print("No files {} found in {}".format(pjoin(fold, name) + ".[0-9]*", fold)) print("Trying {}".format(pjoin(fold, name) + ".vtk")) files = glob(pjoin(fold, name) + ".vtk") if files: return load_state_1D_vtk(files[0]) else: print("Nothing found.") return io = MeshioLibIO(files[0]) coors = io.read(Mesh()).coors[:, 0, None] data = io.read_data(step=0) var_name = head([k for k in data.keys() if "_modal" in k])[:-1] if var_name is None: print("File {} does not contain modal data.".format(files[0])) return porder = len([k for k in data.keys() if var_name in k]) tn = len(files) nts = sorted([int(f.split(".")[-2]) for f in files]) digs = len(files[0].split(".")[-2]) full_name_form = ".".join((pjoin(fold, name), ("{:0" + str(digs) + "d}"), "vtk")) mod_data = nm.zeros((porder, coors.shape[0] - 1, tn, 1)) for i, nt in enumerate(nts): io = MeshioLibIO(full_name_form.format(nt)) # parameter "step" does nothing, but is obligatory data = io.read_data(step=0) for ii in range(porder): mod_data[ii, :, i, 0] = data[var_name+'{}'.format(ii)].data return coors, mod_data
def define(eps0=1e-3, filename_mesh='meshes/3d/piezo_mesh_micro.vtk'): mesh = Mesh.from_file(filename_mesh) bbox = mesh.get_bounding_box() regions = define_box_regions(mesh.dim, bbox[0], bbox[1], eps=1e-3) regions.update({ 'Ymc': 'all', # matrix 'Ym': 'cells of group 1', 'Ym_left': ('r.Ym *v r.Left', 'vertex'), 'Ym_right': ('r.Ym *v r.Right', 'vertex'), 'Ym_bottom': ('r.Ym *v r.Bottom', 'vertex'), 'Ym_top': ('r.Ym *v r.Top', 'vertex'), 'Ym_far': ('r.Ym *v r.Far', 'vertex'), 'Ym_near': ('r.Ym *v r.Near', 'vertex'), 'Gamma_ms': ('r.Ym *v r.Yc', 'facet', 'Ym'), # conductors 'Yc': ('r.Yc1 +c r.Yc2', 'cell'), 'Yc1': 'cells of group 2', 'Yc2': 'cells of group 3', 'Gamma_s1': ('r.Ym *v r.Yc1', 'facet', 'Ym'), 'Gamma_s2': ('r.Ym *v r.Yc2', 'facet', 'Ym'), }) options = { 'coefs_filename': 'coefs_piezo', 'volume': {'value': nm.prod(bbox[1] - bbox[0])}, 'coefs': 'coefs', 'requirements': 'requirements', 'output_dir': 'output', 'file_per_var': True, 'absolute_mesh_path': True, 'multiprocessing': False, 'recovery_hook': recovery_micro, } fields = { 'displacement': ('real', 'vector', 'Ymc', 1), 'potential': ('real', 'scalar', 'Ym', 1), 'sfield': ('real', 'scalar', 'Ymc', 1), } variables = { # displacement 'u': ('unknown field', 'displacement'), 'v': ('test field', 'displacement', 'u'), 'Pi_u': ('parameter field', 'displacement', 'u'), 'U1': ('parameter field', 'displacement', '(set-to-None)'), 'U2': ('parameter field', 'displacement', '(set-to-None)'), # potential 'r': ('unknown field', 'potential'), 's': ('test field', 'potential', 'r'), 'Pi_r': ('parameter field', 'potential', 'r'), 'R1': ('parameter field', 'potential', '(set-to-None)'), 'R2': ('parameter field', 'potential', '(set-to-None)'), # auxiliary 'svar': ('parameter field', 'sfield', '(set-to-None)'), } epbcs = { 'p_ux': (['Left', 'Right'], {'u.all': 'u.all'}, 'match_x_plane'), 'p_uy': (['Near', 'Far'], {'u.all': 'u.all'}, 'match_y_plane'), 'p_uz': (['Bottom', 'Top'], {'u.all': 'u.all'}, 'match_z_plane'), 'p_rx': (['Ym_left', 'Ym_right'], {'r.0': 'r.0'}, 'match_x_plane'), 'p_ry': (['Ym_near', 'Ym_far'], {'r.0': 'r.0'}, 'match_y_plane'), 'p_rz': (['Ym_bottom', 'Ym_top'], {'r.0': 'r.0'}, 'match_z_plane'), } periodic = { 'per_u': ['per_u_x', 'per_u_y', 'per_u_z'], 'per_r': ['per_r_x', 'per_r_y', 'per_r_z'], } # rescale piezoelectric material parameters mat_g_sc, mat_d_sc = (eps0, eps0**2) materials = { 'elastic': ({ 'D': { 'Ym': nm.array([[1.504, 0.656, 0.659, 0, 0, 0], [0.656, 1.504, 0.659, 0, 0, 0], [0.659, 0.659, 1.455, 0, 0, 0], [0, 0, 0, 0.424, 0, 0], [0, 0, 0, 0, 0.439, 0], [0, 0, 0, 0, 0, 0.439]]) * 1e11, 'Yc': stiffness_from_youngpoisson(3, 200e9, 0.25)}},), 'piezo': ({ 'g': nm.array([[0, 0, 0, 0, 11.404, 0], [0, 0, 0, 0, 0, 11.404], [-4.322, -4.322, 17.360, 0, 0, 0]]) / mat_g_sc, 'd': nm.array([[1.284, 0, 0], [0, 1.284, 0], [0, 0, 1.505]]) * 1e-8 / mat_d_sc},), } functions = { 'match_x_plane': (per.match_x_plane,), 'match_y_plane': (per.match_y_plane,), 'match_z_plane': (per.match_z_plane,), } ebcs = { 'fixed_u': ('Corners', {'u.all': 0.0}), 'fixed_r': ('Gamma_ms', {'r.all': 0.0}), 'fixed_r1_s1': ('Gamma_s1', {'r.0': 1.0}), 'fixed_r0_s1': ('Gamma_s1', {'r.0': 0.0}), 'fixed_r1_s2': ('Gamma_s2', {'r.0': 1.0}), 'fixed_r0_s2': ('Gamma_s2', {'r.0': 0.0}), } integrals = { 'i2': 2, } solvers = { 'ls_d': ('ls.scipy_direct', {}), 'ls_i': ('ls.scipy_iterative', {}), 'ns_ea6': ('nls.newton', {'eps_a': 1e6, 'eps_r': 1e-3,}), 'ns_ea0': ('nls.newton', {'eps_a': 1e0, 'eps_r': 1e-3,}), } coefs = { 'A1': { 'status': 'auxiliary', 'requires': ['pis_u', 'corrs_rs'], 'expression': 'dw_lin_elastic.i2.Ymc(elastic.D, U1, U2)', 'set_variables': [('U1', ('corrs_rs', 'pis_u'), 'u'), ('U2', ('corrs_rs', 'pis_u'), 'u')], 'class': cb.CoefSymSym, }, 'A2': { 'status': 'auxiliary', 'requires': ['corrs_rs'], 'expression': 'dw_diffusion.i2.Ym(piezo.d, R1, R2)', 'set_variables': [('R1', 'corrs_rs', 'r'), ('R2', 'corrs_rs', 'r')], 'class': cb.CoefSymSym, }, 'A': { 'requires': ['c.A1', 'c.A2'], 'expression': 'c.A1 + c.A2', 'class': cb.CoefEval, }, 'vol': { 'regions': ['Ym', 'Yc1', 'Yc2'], 'expression': 'd_volume.i2.%s(svar)', 'class': cb.VolumeFractions, }, 'eps0': { 'requires': [], 'expression': '%e' % eps0, 'class': cb.CoefEval, }, 'filenames': {}, } requirements = { 'pis_u': { 'variables': ['u'], 'class': cb.ShapeDimDim, }, 'pis_r': { 'variables': ['r'], 'class': cb.ShapeDim, }, 'corrs_rs': { 'requires': ['pis_u'], 'ebcs': ['fixed_u', 'fixed_r'], 'epbcs': ['p_ux', 'p_uy', 'p_uz', 'p_rx', 'p_ry', 'p_rz'], 'equations': { 'eq1': """dw_lin_elastic.i2.Ymc(elastic.D, v, u) - dw_piezo_coupling.i2.Ym(piezo.g, v, r) = - dw_lin_elastic.i2.Ymc(elastic.D, v, Pi_u)""", 'eq2': """ - dw_piezo_coupling.i2.Ym(piezo.g, u, s) - dw_diffusion.i2.Ym(piezo.d, s, r) = dw_piezo_coupling.i2.Ym(piezo.g, Pi_u, s)""", }, 'set_variables': [('Pi_u', 'pis_u', 'u')], 'class': cb.CorrDimDim, 'save_name': 'corrs_rs', 'solvers': {'ls': 'ls_i', 'nls': 'ns_ea6'}, }, } # define requirements and coefficients related to conductors bc_conductors = [ ['fixed_r1_s1', 'fixed_r0_s2'], # phi = 1 on S1, phi = 0 on S2 ['fixed_r1_s2', 'fixed_r0_s1'], # phi = 0 on S1, phi = 1 on S2 ] for k in range(2): sk = '%d' % k requirements.update({ 'corrs_k' + sk: { 'requires': ['pis_r'], 'ebcs': ['fixed_u'] + bc_conductors[k], 'epbcs': ['p_ux', 'p_uy', 'p_uz', 'p_rx', 'p_ry', 'p_rz'], 'equations': { 'eq1': """dw_lin_elastic.i2.Ymc(elastic.D, v, u) - dw_piezo_coupling.i2.Ym(piezo.g, v, r) = 0""", 'eq2': """ - dw_piezo_coupling.i2.Ym(piezo.g, u, s) - dw_diffusion.i2.Ym(piezo.d, s, r) = 0""" }, 'class': cb.CorrOne, 'save_name': 'corrs_k' + sk, 'solvers': {'ls': 'ls_d', 'nls': 'ns_ea0'}, }, }) coefs.update({ 'V1_' + sk: { 'status': 'auxiliary', 'requires': ['pis_u', 'corrs_k' + sk], 'expression': 'dw_lin_elastic.i2.Ymc(elastic.D, U1, U2)', 'set_variables': [('U1', 'corrs_k' + sk, 'u'), ('U2', 'pis_u', 'u')], 'class': cb.CoefSym, }, 'V2_' + sk: { 'status': 'auxiliary', 'requires': ['pis_u', 'corrs_k' + sk], 'expression': 'dw_piezo_coupling.i2.Ym(piezo.g, U1, R1)', 'set_variables': [('R1', 'corrs_k' + sk, 'r'), ('U1', 'pis_u', 'u')], 'class': cb.CoefSym, }, 'V' + sk: { 'requires': ['c.V1_' + sk, 'c.V2_' + sk], 'expression': 'c.V1_%s - c.V2_%s' % (sk, sk), 'class': cb.CoefEval, }, }) return locals()