def __init__(self, name, nurbs, bmesh, regions=None, **kwargs): """ Create an IGA domain. Parameters ---------- name : str The domain name. """ Domain.__init__(self, name, nurbs=nurbs, bmesh=bmesh, regions=regions, **kwargs) from sfepy.discrete.fem.geometry_element import create_geometry_elements from sfepy.discrete.fem import Mesh from sfepy.discrete.fem.utils import prepare_remap tconn = iga.get_bezier_topology(bmesh.conn, nurbs.degrees) itc = nm.unique(tconn) remap = prepare_remap(itc, bmesh.conn.max() + 1) ltcoors = bmesh.cps[itc] ltconn = remap[tconn] n_nod, dim = ltcoors.shape n_el = ltconn.shape[0] self.shape = Struct(n_nod=n_nod, dim=dim, tdim=0, n_el=n_el) desc = '%d_%d' % (dim, bmesh.conn.shape[1]) mat_id = nm.zeros(bmesh.conn.shape[0], dtype=nm.int32) eval_mesh = Mesh.from_data(self.name + '_eval', nurbs.cps, None, [nurbs.conn], [mat_id], [desc]) self.eval_mesh = eval_mesh desc = '%d_%d' % (dim, 2**dim) mat_id = nm.zeros(ltconn.shape[0], dtype=nm.int32) self.mesh = Mesh.from_data(self.name + '_topo', ltcoors, None, [ltconn], [mat_id], [desc]) self.cmesh = self.mesh.cmesh gels = create_geometry_elements() self.cmesh.set_local_entities(gels) self.cmesh.setup_entities() self.shape.tdim = self.cmesh.tdim self.gel = gels[desc] if regions is not None: self.vertex_set_bcs = {} for key, val in six.iteritems(self.regions): self.vertex_set_bcs[key] = remap[val] self.reset_regions()
def __init__(self, name, nurbs, bmesh, regions=None, **kwargs): """ Create an IGA domain. Parameters ---------- name : str The domain name. """ Domain.__init__(self, name, nurbs=nurbs, bmesh=bmesh, regions=regions, **kwargs) from sfepy.discrete.fem.geometry_element import create_geometry_elements from sfepy.discrete.fem import Mesh from sfepy.discrete.fem.utils import prepare_remap tconn = iga.get_bezier_topology(bmesh.conn, nurbs.degrees) itc = nm.unique(tconn) remap = prepare_remap(itc, bmesh.conn.max() + 1) ltcoors = bmesh.cps[itc] ltconn = remap[tconn] n_nod, dim = ltcoors.shape n_el = ltconn.shape[0] self.shape = Struct(n_nod=n_nod, dim=dim, tdim=0, n_el=n_el) desc = '%d_%d' % (dim, bmesh.conn.shape[1]) mat_id = nm.zeros(bmesh.conn.shape[0], dtype=nm.int32) eval_mesh = Mesh.from_data(self.name + '_eval', nurbs.cps, None, [nurbs.conn], [mat_id], [desc]) self.eval_mesh = eval_mesh desc = '%d_%d' % (dim, 2**dim) mat_id = nm.zeros(ltconn.shape[0], dtype=nm.int32) self.mesh = Mesh.from_data(self.name + '_topo', ltcoors, None, [ltconn], [mat_id], [desc]) self.cmesh = self.mesh.cmesh gels = create_geometry_elements() self.cmesh.set_local_entities(gels) self.cmesh.setup_entities() self.shape.tdim = self.cmesh.tdim self.gel = gels[desc] if regions is not None: self.vertex_set_bcs = {} for key, val in self.regions.iteritems(): self.vertex_set_bcs[key] = remap[val] self.reset_regions()
def _get_bqp(geometry, order): from sfepy.discrete import Integral from sfepy.discrete.fem.geometry_element import GeometryElement from sfepy.discrete.fem import Mesh, FEDomain, Field gel = GeometryElement(geometry) mesh = Mesh.from_data('aux', gel.coors, None, [gel.conn[None, :]], [[0]], [geometry]) domain = FEDomain('domain', mesh) omega = domain.create_region('Omega', 'all') surf = domain.create_region('Surf', 'vertices of surface', 'facet') field = Field.from_args('f', nm.float64, shape=1, region=omega, approx_order=1) field.setup_surface_data(surf) integral = Integral('aux', order=order) field.create_bqp('Surf', integral) sd = field.surface_data['Surf'] qp = field.qp_coors[(integral.order, sd.bkey)] output('geometry:', geometry, 'order:', order, 'num. points:', qp.vals.shape[1], 'true_order:', integral.qps[gel.surface_facet_name].order) output('min. weight:', qp.weights.min()) output('max. weight:', qp.weights.max()) return (gel, qp.vals.reshape( (-1, mesh.dim)), nm.tile(qp.weights, qp.vals.shape[0]))
def triangulate(mesh, verbose=False): """ Triangulate a 2D or 3D tensor product mesh: quadrilaterals->triangles, hexahedrons->tetrahedrons. Parameters ---------- mesh : Mesh The input mesh. Returns ------- mesh : Mesh The triangulated mesh. """ conns = None for k, new_desc in [('3_8', '3_4'), ('2_4', '2_3')]: if k in mesh.descs: conns = mesh.get_conn(k) break if conns is not None: nelo = conns.shape[0] output('initial mesh: %d elements' % nelo, verbose=verbose) new_conns = elems_q2t(conns) nn = new_conns.shape[0] // nelo new_cgroups = nm.repeat(mesh.cmesh.cell_groups, nn) output('new mesh: %d elements' % new_conns.shape[0], verbose=verbose) mesh = Mesh.from_data(mesh.name, mesh.coors, mesh.cmesh.vertex_groups, [new_conns], [new_cgroups], [new_desc]) return mesh
def gen_two_bodies(dims0, shape0, centre0, dims1, shape1, centre1, shift1): from sfepy.discrete.fem import Mesh from sfepy.mesh.mesh_generators import gen_block_mesh m0 = gen_block_mesh(dims0, shape0, centre0) m1 = gen_block_mesh(dims1, shape1, centre1) coors = nm.concatenate((m0.coors, m1.coors + shift1), axis=0) desc = m0.descs[0] c0 = m0.get_conn(desc) c1 = m1.get_conn(desc) conn = nm.concatenate((c0, c1 + m0.n_nod), axis=0) ngroups = nm.zeros(coors.shape[0], dtype=nm.int32) ngroups[m0.n_nod:] = 1 mat_id = nm.zeros(conn.shape[0], dtype=nm.int32) mat_id[m0.n_el:] = 1 name = 'two_bodies.mesh' mesh = Mesh.from_data(name, coors, ngroups, [conn], [mat_id], m0.descs) mesh.write(name, io='auto') return mesh
def save_basis(nurbs, pars): """ Save a NURBS object basis on a FE mesh corresponding to the given parametrization in VTK files. Parameters ---------- nurbs : igakit.nurbs.NURBS instance The NURBS object. pars : sequence of array, optional The values of parameters in each parametric dimension. """ coors, conn, desc = create_linear_fe_mesh(nurbs, pars) mat_id = nm.zeros(conn.shape[0], dtype=nm.int32) mesh = Mesh.from_data('nurbs', coors, None, [conn], [mat_id], [desc]) n_dof = nurbs.weights.ravel().shape[0] variable = nm.zeros(n_dof, dtype=nm.float64) field = variable.reshape(nurbs.weights.shape) for ic in xrange(n_dof): variable[ic - 1] = 0.0 variable[ic] = 1.0 vals = nurbs.evaluate(field, *pars).reshape((-1)) out = {} out['bf'] = Struct(name='output_data', mode='vertex', data=vals[:, None]) mesh.write('iga_basis_%03d.vtk' % ic, io='auto', out=out)
def refine_3_8(mesh_in, cmesh): """ Refines hexahedral mesh by cutting cutting each edge in half and making 8 new finer hexahedrons out of one coarser one. """ # Unique edge centres. e_centres = cmesh.get_centroids(cmesh.dim - 2) # Unique face centres. f_centres = cmesh.get_centroids(cmesh.dim - 1) # Unique element centres. coors = mesh_in.get_element_coors() centres = 0.125 * nm.sum(coors, axis=1) # New coordinates after the original ones. coors = nm.r_[mesh_in.coors, e_centres, f_centres, centres] o1 = mesh_in.n_nod o2 = o1 + e_centres.shape[0] o3 = o2 + f_centres.shape[0] ecc = cmesh.get_conn(cmesh.dim, cmesh.dim - 2) eoffs = ecc.offsets fcc = cmesh.get_conn(cmesh.dim, cmesh.dim - 1) foffs = fcc.offsets st = nm.vstack conns = [] mat_ids = [] for ig, conn in enumerate(mesh_in.conns): off0, off1 = mesh_in.el_offsets[ig : ig + 2] n_el = conn.shape[0] e_nodes = ecc.indices[eoffs[off0]:eoffs[off1]].reshape((n_el, 12)) + o1 f_nodes = fcc.indices[foffs[off0]:foffs[off1]].reshape((n_el, 6)) + o2 nodes = nm.arange(n_el) + off0 + o3 c = nm.c_[conn, e_nodes, f_nodes, nodes].T new_conn = st([c[0], c[8], c[20], c[11], c[16], c[22], c[26], c[21], c[1], c[9], c[20], c[8], c[17], c[24], c[26], c[22], c[2], c[10], c[20], c[9], c[18], c[25], c[26], c[24], c[3], c[11], c[20], c[10], c[19], c[21], c[26], c[25], c[4], c[15], c[23], c[12], c[16], c[21], c[26], c[22], c[5], c[12], c[23], c[13], c[17], c[22], c[26], c[24], c[6], c[13], c[23], c[14], c[18], c[24], c[26], c[25], c[7], c[14], c[23], c[15], c[19], c[25], c[26], c[21]]).T new_conn = new_conn.reshape((8 * n_el, 8)) conns.append(new_conn) new_mat_id = mesh_in.mat_ids[ig].repeat(8) mat_ids.append(new_mat_id) mesh = Mesh.from_data(mesh_in.name + '_r', coors, None, conns, mat_ids, mesh_in.descs ) return mesh
def refine_2_3(mesh_in): """ Refines mesh out of triangles by cutting cutting each edge in half and making 4 new finer triangles out of one coarser one. """ cmesh = mesh_in.cmesh # Unique edge centres. e_centres = cmesh.get_centroids(cmesh.dim - 1) # New coordinates after the original ones. coors = nm.r_[mesh_in.coors, e_centres] o1 = mesh_in.n_nod cc = cmesh.get_conn(cmesh.dim, cmesh.dim - 1) conn = mesh_in.get_conn('2_3') n_el = conn.shape[0] e_nodes = cc.indices.reshape((n_el, 3)) + o1 c = nm.c_[conn, e_nodes].T new_conn = nm.vstack([ c[0], c[3], c[5], c[3], c[4], c[5], c[1], c[4], c[3], c[2], c[5], c[4] ]).T new_conn = new_conn.reshape((4 * n_el, 3)) new_mat_id = cmesh.cell_groups.repeat(4) mesh = Mesh.from_data(mesh_in.name + '_r', coors, None, [new_conn], [new_mat_id], mesh_in.descs) return mesh
def _get_bqp(geometry, order): from sfepy.discrete import Integral from sfepy.discrete.fem.geometry_element import GeometryElement from sfepy.discrete.fem import Mesh, FEDomain, Field gel = GeometryElement(geometry) mesh = Mesh.from_data('aux', gel.coors, None, [gel.conn[None, :]], [[0]], [geometry]) domain = FEDomain('domain', mesh) omega = domain.create_region('Omega', 'all') surf = domain.create_region('Surf', 'vertices of surface', 'facet') field = Field.from_args('f', nm.float64, shape=1, region=omega, approx_order=1) field.setup_surface_data(surf) integral = Integral('aux', order=order) field.create_bqp('Surf', integral) sd = field.surface_data['Surf'] qp = field.qp_coors[(integral.order, sd.bkey)] output('geometry:', geometry, 'order:', order, 'num. points:', qp.vals.shape[1], 'true_order:', integral.qps[gel.surface_facet_name].order) output('min. weight:', qp.weights.min()) output('max. weight:', qp.weights.max()) return (gel, qp.vals.reshape((-1, mesh.dim)), nm.tile(qp.weights, qp.vals.shape[0]))
def refine_3_4(mesh_in, cmesh): """ Refines tetrahedra by cutting each edge in half and making 8 new finer tetrahedra out of one coarser one. Old nodal coordinates come first in `coors`, then the new ones. The new tetrahedra are similar to the old one, no degeneration is supposed to occur as at most 3 congruence classes of tetrahedra appear, even when re-applied iteratively (provided that `conns` are not modified between two applications - ordering of vertices in tetrahedra matters not only for positivity of volumes). References: - Juergen Bey: Simplicial grid refinement: on Freudenthal s algorithm and the optimal number of congruence classes, Numer.Math. 85 (2000), no. 1, 1--29, or - Juergen Bey: Tetrahedral grid refinement, Computing 55 (1995), no. 4, 355--378, or http://citeseer.ist.psu.edu/bey95tetrahedral.html """ # Unique edge centres. e_centres = cmesh.get_centroids(cmesh.dim - 2) # New coordinates after the original ones. coors = nm.r_[mesh_in.coors, e_centres] o1 = mesh_in.n_nod cc = cmesh.get_conn(cmesh.dim, cmesh.dim - 2) offs = cc.offsets conns = [] mat_ids = [] for ig, conn in enumerate(mesh_in.conns): off0, off1 = mesh_in.el_offsets[ig : ig + 2] n_el = conn.shape[0] e_nodes = cc.indices[offs[off0]:offs[off1]].reshape((n_el, 6)) + o1 c = nm.c_[conn, e_nodes].T new_conn = nm.vstack([c[0], c[4], c[6], c[7], c[4], c[1], c[5], c[8], c[6], c[5], c[2], c[9], c[7], c[8], c[9], c[3], c[4], c[6], c[7], c[8], c[4], c[6], c[8], c[5], c[6], c[7], c[8], c[9], c[6], c[5], c[9], c[8]]).T new_conn = new_conn.reshape((8 * n_el, 4)) conns.append(new_conn) new_mat_id = mesh_in.mat_ids[ig].repeat(8) mat_ids.append(new_mat_id) mesh = Mesh.from_data(mesh_in.name + '_r', coors, None, conns, mat_ids, mesh_in.descs ) return mesh
def __init__(self, name, nurbs, bmesh, regions=None, **kwargs): """ Create an IGA domain. Parameters ---------- name : str The domain name. """ Domain.__init__(self, name, nurbs=nurbs, bmesh=bmesh, regions=regions, **kwargs) from sfepy.discrete.fem.geometry_element import create_geometry_elements from sfepy.discrete.fem import Mesh from sfepy.discrete.fem.extmods.cmesh import CMesh from sfepy.discrete.fem.utils import prepare_remap ac = nm.ascontiguousarray self.nurbs.cs = [ac(nm.array(cc, dtype=nm.float64)[:, None, ...]) for cc in self.nurbs.cs] self.nurbs.degrees = self.nurbs.degrees.astype(nm.int32) self.facets = iga.get_bezier_element_entities(nurbs.degrees) tconn = iga.get_bezier_topology(bmesh.conn, nurbs.degrees) itc = nm.unique(tconn) remap = prepare_remap(itc, bmesh.conn.max() + 1) ltcoors = bmesh.cps[itc] ltconn = remap[tconn] n_nod, dim = ltcoors.shape n_el = ltconn.shape[0] self.shape = Struct(n_nod=n_nod, dim=dim, tdim=0, n_el=n_el, n_gr=1) desc = '%d_%d' % (dim, 2**dim) mat_id = nm.zeros(ltconn.shape[0], dtype=nm.int32) self.mesh = Mesh.from_data(self.name + '_topo', ltcoors, None, [ltconn], [mat_id], [desc]) self.cmesh = CMesh.from_mesh(self.mesh) gels = create_geometry_elements() self.cmesh.set_local_entities(gels) self.cmesh.setup_entities() self.shape.tdim = self.cmesh.tdim self.gel = gels[desc] if regions is not None: self.vertex_set_bcs = {} for key, val in self.regions.iteritems(): self.vertex_set_bcs[key] = remap[val] self.cell_offsets = {0 : 0} self.reset_regions()
def refine_region(domain0, region0, region1): """ Coarse cell sub_cells[ii, 0] in mesh0 is split into sub_cells[ii, 1:] in mesh1. The new fine cells are interleaved among the original coarse cells so that the indices of the coarse cells do not change. The cell groups are preserved. The vertex groups are preserved only in the coarse (non-refined) cells. """ if region1 is None: return domain0, None mesh0 = domain0.mesh mesh1 = Mesh.from_region(region1, mesh0) domain1 = FEDomain('d', mesh1) domain1r = domain1.refine() mesh1r = domain1r.mesh n_cell = region1.shape.n_cell n_sub = 4 if mesh0.cmesh.tdim == 2 else 8 sub_cells = nm.empty((n_cell, n_sub + 1), dtype=nm.uint32) sub_cells[:, 0] = region1.cells sub_cells[:, 1] = region1.cells aux = nm.arange((n_sub - 1) * n_cell, dtype=nm.uint32) sub_cells[:, 2:] = mesh0.n_el + aux.reshape((n_cell, -1)) coors0, vgs0, conns0, mat_ids0, descs0 = mesh0._get_io_data() coors, vgs, _conns, _mat_ids, descs = mesh1r._get_io_data() # Preserve vertex groups of non-refined cells. vgs[:len(vgs0)] = vgs0 def _interleave_refined(c0, c1): if c1.ndim == 1: c0 = c0[:, None] c1 = c1[:, None] n_row, n_col = c1.shape n_new = region0.shape.n_cell + n_row out = nm.empty((n_new, n_col), dtype=c0.dtype) out[region0.cells] = c0[region0.cells] out[region1.cells] = c1[::n_sub] aux = c1.reshape((-1, n_col * n_sub)) out[mesh0.n_el:] = aux[:, n_col:].reshape((-1, n_col)) return out conn = _interleave_refined(conns0[0], _conns[0]) mat_id = _interleave_refined(mat_ids0[0], _mat_ids[0]).squeeze() mesh = Mesh.from_data('a', coors, vgs, [conn], [mat_id], descs) domain = FEDomain('d', mesh) return domain, sub_cells
def refine_3_4(mesh_in, cmesh): """ Refines tetrahedra by cutting each edge in half and making 8 new finer tetrahedra out of one coarser one. Old nodal coordinates come first in `coors`, then the new ones. The new tetrahedra are similar to the old one, no degeneration is supposed to occur as at most 3 congruence classes of tetrahedra appear, even when re-applied iteratively (provided that `conns` are not modified between two applications - ordering of vertices in tetrahedra matters not only for positivity of volumes). References: - Juergen Bey: Simplicial grid refinement: on Freudenthal s algorithm and the optimal number of congruence classes, Numer.Math. 85 (2000), no. 1, 1--29, or - Juergen Bey: Tetrahedral grid refinement, Computing 55 (1995), no. 4, 355--378, or http://citeseer.ist.psu.edu/bey95tetrahedral.html """ # Unique edge centres. e_centres = cmesh.get_centroids(cmesh.dim - 2) # New coordinates after the original ones. coors = nm.r_[mesh_in.coors, e_centres] o1 = mesh_in.n_nod cc = cmesh.get_conn(cmesh.dim, cmesh.dim - 2) offs = cc.offsets conns = [] mat_ids = [] for ig, conn in enumerate(mesh_in.conns): off0, off1 = mesh_in.el_offsets[ig:ig + 2] n_el = conn.shape[0] e_nodes = cc.indices[offs[off0]:offs[off1]].reshape((n_el, 6)) + o1 c = nm.c_[conn, e_nodes].T new_conn = nm.vstack([ c[0], c[4], c[6], c[7], c[4], c[1], c[5], c[8], c[6], c[5], c[2], c[9], c[7], c[8], c[9], c[3], c[4], c[6], c[7], c[8], c[4], c[6], c[8], c[5], c[6], c[7], c[8], c[9], c[6], c[5], c[9], c[8] ]).T new_conn = new_conn.reshape((8 * n_el, 4)) conns.append(new_conn) new_mat_id = mesh_in.mat_ids[ig].repeat(8) mat_ids.append(new_mat_id) mesh = Mesh.from_data(mesh_in.name + '_r', coors, None, conns, mat_ids, mesh_in.descs) return mesh
def refine_3_8(mesh_in): """ Refines hexahedral mesh by cutting cutting each edge in half and making 8 new finer hexahedrons out of one coarser one. """ cmesh = mesh_in.cmesh # Unique edge centres. e_centres = cmesh.get_centroids(cmesh.dim - 2) # Unique face centres. f_centres = cmesh.get_centroids(cmesh.dim - 1) # Unique element centres. centres = cmesh.get_centroids(cmesh.dim) # New coordinates after the original ones. coors = nm.r_[mesh_in.coors, e_centres, f_centres, centres] o1 = mesh_in.n_nod o2 = o1 + e_centres.shape[0] o3 = o2 + f_centres.shape[0] ecc = cmesh.get_conn(cmesh.dim, cmesh.dim - 2) fcc = cmesh.get_conn(cmesh.dim, cmesh.dim - 1) conn = mesh_in.get_conn('3_8') n_el = conn.shape[0] st = nm.vstack e_nodes = ecc.indices.reshape((n_el, 12)) + o1 f_nodes = fcc.indices.reshape((n_el, 6)) + o2 nodes = nm.arange(n_el) + o3 c = nm.c_[conn, e_nodes, f_nodes, nodes].T new_conn = st([ c[0], c[8], c[20], c[11], c[16], c[22], c[26], c[21], c[1], c[9], c[20], c[8], c[17], c[24], c[26], c[22], c[2], c[10], c[20], c[9], c[18], c[25], c[26], c[24], c[3], c[11], c[20], c[10], c[19], c[21], c[26], c[25], c[4], c[15], c[23], c[12], c[16], c[21], c[26], c[22], c[5], c[12], c[23], c[13], c[17], c[22], c[26], c[24], c[6], c[13], c[23], c[14], c[18], c[24], c[26], c[25], c[7], c[14], c[23], c[15], c[19], c[25], c[26], c[21] ]).T new_conn = new_conn.reshape((8 * n_el, 8)) new_mat_id = cmesh.cell_groups.repeat(8) mesh = Mesh.from_data(mesh_in.name + '_r', coors, None, [new_conn], [new_mat_id], mesh_in.descs) return mesh
def refine_3_8(mesh_in): """ Refines hexahedral mesh by cutting cutting each edge in half and making 8 new finer hexahedrons out of one coarser one. """ cmesh = mesh_in.cmesh # Unique edge centres. e_centres = cmesh.get_centroids(cmesh.dim - 2) # Unique face centres. f_centres = cmesh.get_centroids(cmesh.dim - 1) # Unique element centres. centres = cmesh.get_centroids(cmesh.dim) # New coordinates after the original ones. coors = nm.r_[mesh_in.coors, e_centres, f_centres, centres] o1 = mesh_in.n_nod o2 = o1 + e_centres.shape[0] o3 = o2 + f_centres.shape[0] ecc = cmesh.get_conn(cmesh.dim, cmesh.dim - 2) fcc = cmesh.get_conn(cmesh.dim, cmesh.dim - 1) conn = mesh_in.get_conn('3_8') n_el = conn.shape[0] st = nm.vstack e_nodes = ecc.indices.reshape((n_el, 12)) + o1 f_nodes = fcc.indices.reshape((n_el, 6)) + o2 nodes = nm.arange(n_el) + o3 c = nm.c_[conn, e_nodes, f_nodes, nodes].T new_conn = st([c[0], c[8], c[20], c[11], c[16], c[22], c[26], c[21], c[1], c[9], c[20], c[8], c[17], c[24], c[26], c[22], c[2], c[10], c[20], c[9], c[18], c[25], c[26], c[24], c[3], c[11], c[20], c[10], c[19], c[21], c[26], c[25], c[4], c[15], c[23], c[12], c[16], c[21], c[26], c[22], c[5], c[12], c[23], c[13], c[17], c[22], c[26], c[24], c[6], c[13], c[23], c[14], c[18], c[24], c[26], c[25], c[7], c[14], c[23], c[15], c[19], c[25], c[26], c[21]]).T new_conn = new_conn.reshape((8 * n_el, 8)) new_mat_id = cmesh.cell_groups.repeat(8) mesh = Mesh.from_data(mesh_in.name + '_r', coors, None, [new_conn], [new_mat_id], mesh_in.descs ) return mesh
def create_mesh_and_output(nurbs, pars=None, **kwargs): """ Create a nD-linear tensor product FE mesh using :func:`create_linear_fe_mesh()`, evaluate field variables given as keyword arguments in the mesh vertices and create a dictionary of output data usable by Mesh.write(). Parameters ---------- nurbs : igakit.nurbs.NURBS instance The NURBS object. pars : sequence of array, optional The values of parameters in each parametric dimension. If not given, the values are set so that the resulting mesh has the same number of vertices as the number of control points/basis functions of the NURBS object. **kwargs : kwargs The field variables as keyword arguments. Their names serve as keys in the output dictionary. Returns ------- mesh : Mesh instance The finite element mesh. out : dict The output dictionary. """ coors, conn, desc = create_linear_fe_mesh(nurbs, pars) mat_id = nm.zeros(conn.shape[0], dtype=nm.int32) mesh = Mesh.from_data('nurbs', coors, None, [conn], [mat_id], [desc]) out = {} for key, variable in kwargs.iteritems(): if variable.ndim == 2: nc = variable.shape[1] field = variable.reshape(nurbs.weights.shape + (nc, )) else: field = variable.reshape(nurbs.weights.shape) nc = 1 vals = nurbs.evaluate(field, *pars) out[key] = Struct(name='output_data', mode='vertex', data=vals.reshape((-1, nc))) return mesh, out
def create_mesh_and_output(nurbs, pars=None, **kwargs): """ Create a nD-linear tensor product FE mesh using :func:`create_linear_fe_mesh()`, evaluate field variables given as keyword arguments in the mesh vertices and create a dictionary of output data usable by Mesh.write(). Parameters ---------- nurbs : igakit.nurbs.NURBS instance The NURBS object. pars : sequence of array, optional The values of parameters in each parametric dimension. If not given, the values are set so that the resulting mesh has the same number of vertices as the number of control points/basis functions of the NURBS object. **kwargs : kwargs The field variables as keyword arguments. Their names serve as keys in the output dictionary. Returns ------- mesh : Mesh instance The finite element mesh. out : dict The output dictionary. """ coors, conn, desc = create_linear_fe_mesh(nurbs, pars) mat_id = nm.zeros(conn.shape[0], dtype=nm.int32) mesh = Mesh.from_data('nurbs', coors, None, [conn], [mat_id], [desc]) out = {} for key, variable in kwargs.iteritems(): if variable.ndim == 2: nc = variable.shape[1] field = variable.reshape(nurbs.weights.shape + (nc,)) else: field = variable.reshape(nurbs.weights.shape) nc = 1 vals = nurbs.evaluate(field, *pars) out[key] = Struct(name='output_data', mode='vertex', data=vals.reshape((-1, nc))) return mesh, out
def refine_2_4(mesh_in, cmesh): """ Refines mesh out of quadrilaterals by cutting cutting each edge in half and making 4 new finer quadrilaterals out of one coarser one. """ # Unique edge centres. e_centres = cmesh.get_centroids(cmesh.dim - 1) # Unique element centres. centres = cmesh.get_centroids(cmesh.dim) # New coordinates after the original ones. coors = nm.r_[mesh_in.coors, e_centres, centres] o1 = mesh_in.n_nod o2 = o1 + e_centres.shape[0] cc = cmesh.get_conn(cmesh.dim, cmesh.dim - 1) offs = cc.offsets conns = [] mat_ids = [] for ig, conn in enumerate(mesh_in.conns): off0, off1 = mesh_in.el_offsets[ig:ig + 2] n_el = conn.shape[0] e_nodes = cc.indices[offs[off0]:offs[off1]].reshape((n_el, 4)) + o1 nodes = nm.arange(n_el) + off0 + o2 c = nm.c_[conn, e_nodes, nodes].T new_conn = nm.vstack([ c[0], c[4], c[8], c[7], c[1], c[5], c[8], c[4], c[2], c[6], c[8], c[5], c[3], c[7], c[8], c[6] ]).T new_conn = new_conn.reshape((4 * n_el, 4)) conns.append(new_conn) new_mat_id = mesh_in.mat_ids[ig].repeat(4) mat_ids.append(new_mat_id) mesh = Mesh.from_data(mesh_in.name + '_r', coors, None, conns, mat_ids, mesh_in.descs) return mesh
def refine_2_4(mesh_in, cmesh): """ Refines mesh out of quadrilaterals by cutting cutting each edge in half and making 4 new finer quadrilaterals out of one coarser one. """ # Unique edge centres. e_centres = cmesh.get_centroids(cmesh.dim - 1) # Unique element centres. centres = cmesh.get_centroids(cmesh.dim) # New coordinates after the original ones. coors = nm.r_[mesh_in.coors, e_centres, centres] o1 = mesh_in.n_nod o2 = o1 + e_centres.shape[0] cc = cmesh.get_conn(cmesh.dim, cmesh.dim - 1) offs = cc.offsets conns = [] mat_ids = [] for ig, conn in enumerate(mesh_in.conns): off0, off1 = mesh_in.el_offsets[ig : ig + 2] n_el = conn.shape[0] e_nodes = cc.indices[offs[off0]:offs[off1]].reshape((n_el, 4)) + o1 nodes = nm.arange(n_el) + off0 + o2 c = nm.c_[conn, e_nodes, nodes].T new_conn = nm.vstack([c[0], c[4], c[8], c[7], c[1], c[5], c[8], c[4], c[2], c[6], c[8], c[5], c[3], c[7], c[8], c[6]]).T new_conn = new_conn.reshape((4 * n_el, 4)) conns.append(new_conn) new_mat_id = mesh_in.mat_ids[ig].repeat(4) mat_ids.append(new_mat_id) mesh = Mesh.from_data(mesh_in.name + '_r', coors, None, conns, mat_ids, mesh_in.descs ) return mesh
def mesh_hook(mesh, mode): """ Generate the 1D mesh. """ if mode == 'read': coors = nm.linspace(XS, XE, n_nod).reshape((n_nod, 1)) conn = nm.arange(n_nod, dtype=nm.int32) \ .repeat(2)[1:-1].reshape((-1, 2)) mat_ids = nm.zeros(n_nod - 1, dtype=nm.int32) descs = ['1_2'] mesh = Mesh.from_data('uniform_1D{}'.format(n_nod), coors, None, [conn], [mat_ids], descs) return mesh elif mode == 'write': pass
def mesh_hook(mesh, mode): """ Generate the 1D mesh. """ if mode == 'read': n_nod = 101 coors = nm.linspace(0.0, 1.0, n_nod).reshape((n_nod, 1)) conn = nm.arange(n_nod, dtype=nm.int32).repeat(2)[1:-1].reshape((-1, 2)) mat_ids = nm.zeros(n_nod - 1, dtype=nm.int32) descs = ['1_2'] mesh = Mesh.from_data('laplace_1d', coors, None, [conn], [mat_ids], descs) return mesh elif mode == 'write': pass
def refine_2_4(mesh_in): """ Refines mesh out of quadrilaterals by cutting cutting each edge in half and making 4 new finer quadrilaterals out of one coarser one. """ cmesh = mesh_in.cmesh # Unique edge centres. e_centres = cmesh.get_centroids(cmesh.dim - 1) # Unique element centres. centres = cmesh.get_centroids(cmesh.dim) # New coordinates after the original ones. coors = nm.r_[mesh_in.coors, e_centres, centres] o1 = mesh_in.n_nod o2 = o1 + e_centres.shape[0] cc = cmesh.get_conn(cmesh.dim, cmesh.dim - 1) conn = mesh_in.get_conn('2_4') n_el = conn.shape[0] e_nodes = cc.indices.reshape((n_el, 4)) + o1 nodes = nm.arange(n_el) + o2 c = nm.c_[conn, e_nodes, nodes].T new_conn = nm.vstack([c[0], c[4], c[8], c[7], c[1], c[5], c[8], c[4], c[2], c[6], c[8], c[5], c[3], c[7], c[8], c[6]]).T new_conn = new_conn.reshape((4 * n_el, 4)) new_mat_id = cmesh.cell_groups.repeat(4) mesh = Mesh.from_data(mesh_in.name + '_r', coors, None, [new_conn], [new_mat_id], mesh_in.descs ) return mesh
def make_mesh(dims, shape, transform=None): """ Generate a 2D rectangle mesh in 3D space, and optionally apply a coordinate transform. """ _mesh = gen_block_mesh(dims, shape, [0, 0], name='shell10x', verbose=False) coors = nm.c_[_mesh.coors, nm.zeros(_mesh.n_nod, dtype=nm.float64)] coors = nm.ascontiguousarray(coors) conns = [_mesh.get_conn(_mesh.descs[0])] mesh = Mesh.from_data(_mesh.name, coors, _mesh.cmesh.vertex_groups, conns, [_mesh.cmesh.cell_groups], _mesh.descs) if transform == 'bend': bbox = mesh.get_bounding_box() x0, x1 = bbox[:, 0] angles = 0.5 * nm.pi * (coors[:, 0] - x0) / (x1 - x0) mtx = make_axis_rotation_matrix([0, -1, 0], angles[:, None, None]) coors = mesh.coors.copy() coors[:, 0] = 0 coors[:, 2] = (x1 - x0) mesh.coors[:] = transform_data(coors, mtx=mtx) mesh.coors[:, 0] -= 0.5 * (x1 - x0) elif transform == 'twist': bbox = mesh.get_bounding_box() x0, x1 = bbox[:, 0] angles = 0.5 * nm.pi * (coors[:, 0] - x0) / (x1 - x0) mtx = make_axis_rotation_matrix([-1, 0, 0], angles[:, None, None]) mesh.coors[:] = transform_data(mesh.coors, mtx=mtx) return mesh
def _permute_quad_face(mesh0): from sfepy.discrete.fem import Mesh coors0, ngroups0, conns0, mat_ids0, desc0 = mesh0._get_io_data() im = nm.arange(4, 8) cperms = [[0, 1, 2, 3], [0, 2, 1, 3], [0, 1, 3, 2]] meshes = [] for ip, cperm in enumerate(cperms): tr = nm.arange(12) tr[im] = tr[im[cperm]] coors = coors0.copy() coors[im] = coors0[im[cperm]] conn = conns0[0].copy() conn = tr[conn] mesh = Mesh.from_data(mesh0.name + str(ip), coors, ngroups0, [conn], mat_ids0, desc0) meshes.append(mesh) return meshes
def refine_1_2(mesh_in): """ Refines 1D mesh by cutting each element in half """ if not nm.all(mesh_in.coors[:-1] <= mesh_in.coors[1:]): raise ValueError("1D Mesh for refinement must have sorted coors array") cmesh = mesh_in.cmesh c_centres = cmesh.get_centroids(cmesh.dim) new_coors = nm.zeros((2*mesh_in.n_nod - 1, 1)) new_coors[0::2] = mesh_in.coors new_coors[1::2] = c_centres n_nod = len(new_coors) new_conn = nm.arange(n_nod, dtype=nm.int32).repeat(2)[1:-1].reshape((-1, 2)) new_mat_id = cmesh.cell_groups.repeat(2) mesh = Mesh.from_data(mesh_in.name + '_r', new_coors, None, [new_conn], [new_mat_id], mesh_in.descs) return mesh
def expand2d(mesh2d, dist, rep): """ Expand 2D planar mesh into 3D volume, convert triangular/quad mesh to tetrahedrons/hexahedrons. Parameters ---------- mesh2d : Mesh The 2D mesh. dist : float The elements size in the 3rd direction. rep : int The number of elements in the 3rd direction. Returns ------- mesh3d : Mesh The 3D mesh. """ if len(mesh2d.descs) > 1: raise ValueError('More than one cell type (%s). Not supported!' % ', '.join(mesh2d.descs)) nel = mesh2d.n_el nnd = mesh2d.n_nod et = mesh2d.descs[0] coors = mesh2d.coors conn = mesh2d.get_conn(et) zcoor = nm.arange(rep + 1) * dist coors3d = nm.hstack([ nm.tile(coors, (rep + 1, 1)), nm.tile(zcoor, (nnd, 1)).T.flatten()[:, nm.newaxis] ]) ngroups = nm.tile(mesh2d.cmesh.vertex_groups, (rep + 1, )) if et == '2_4': descs3d = '3_8' conn3d = nm.zeros((nel * rep, 8), dtype=nm.int32) mats3d = nm.tile(mesh2d.cmesh.cell_groups, (1, rep)).squeeze() elif et == '2_3': descs3d = '3_4' conn3d = nm.zeros((3 * nel * rep, 4), dtype=nm.int32) mats3d = nm.tile(mesh2d.cmesh.cell_groups, (1, 3 * rep)).squeeze() for ii in range(rep): bgn0 = nnd * ii bgn1 = bgn0 + nnd if et == '2_4': bge0 = nel * ii bge1 = bge0 + nel conn3d[bge0:bge1, :4] = conn + bgn0 conn3d[bge0:bge1, 4:] = conn + bgn1 elif et == '2_3': # 0 1 2 5 bge0 = 3 * nel * ii bge1 = bge0 + nel conn3d[bge0:bge1, :] = nm.array([ conn[:, 0] + bgn0, conn[:, 1] + bgn0, conn[:, 2] + bgn0, conn[:, 2] + bgn1 ]).T # 0 1 5 4 bge0 += nel bge1 += nel conn3d[bge0:bge1, :] = nm.array([ conn[:, 0] + bgn0, conn[:, 1] + bgn0, conn[:, 2] + bgn1, conn[:, 1] + bgn1 ]).T # 0 4 5 3 bge0 += nel bge1 += nel conn3d[bge0:bge1, :] = nm.array([ conn[:, 0] + bgn0, conn[:, 1] + bgn1, conn[:, 2] + bgn1, conn[:, 0] + bgn1 ]).T mesh3d = Mesh.from_data('mesh', coors3d, ngroups, [conn3d], [mats3d], [descs3d]) return mesh3d
def main(): parser = ArgumentParser(description=__doc__, formatter_class=RawDescriptionHelpFormatter) parser.add_argument('-s', '--scale', metavar='scale', action='store', dest='scale', default=None, help=helps['scale']) parser.add_argument('-c', '--center', metavar='center', action='store', dest='center', default=None, help=helps['center']) parser.add_argument('-r', '--refine', metavar='level', action='store', type=int, dest='refine', default=0, help=helps['refine']) parser.add_argument('-f', '--format', metavar='format', action='store', type=str, dest='format', default=None, help=helps['format']) parser.add_argument('-l', '--list', action='store_true', dest='list', help=helps['list']) parser.add_argument('-m', '--merge', action='store_true', dest='merge', help=helps['merge']) parser.add_argument('-t', '--tri-tetra', action='store_true', dest='tri_tetra', help=helps['tri-tetra']) parser.add_argument('filename_in') parser.add_argument('filename_out') options = parser.parse_args() if options.list: output('Supported readable mesh formats:') output('--------------------------------') output_mesh_formats('r') output('') output('Supported writable mesh formats:') output('--------------------------------') output_mesh_formats('w') sys.exit(0) scale = _parse_val_or_vec(options.scale, 'scale', parser) center = _parse_val_or_vec(options.center, 'center', parser) filename_in = options.filename_in filename_out = options.filename_out mesh = Mesh.from_file(filename_in) if scale is not None: if len(scale) == 1: tr = nm.eye(mesh.dim, dtype=nm.float64) * scale elif len(scale) == mesh.dim: tr = nm.diag(scale) else: raise ValueError('bad scale! (%s)' % scale) mesh.transform_coors(tr) if center is not None: cc = 0.5 * mesh.get_bounding_box().sum(0) shift = center - cc tr = nm.c_[nm.eye(mesh.dim, dtype=nm.float64), shift[:, None]] mesh.transform_coors(tr) if options.refine > 0: domain = FEDomain(mesh.name, mesh) output('initial mesh: %d nodes %d elements' % (domain.shape.n_nod, domain.shape.n_el)) for ii in range(options.refine): output('refine %d...' % ii) domain = domain.refine() output('... %d nodes %d elements' % (domain.shape.n_nod, domain.shape.n_el)) mesh = domain.mesh if options.tri_tetra > 0: conns = None for k, new_desc in [('3_8', '3_4'), ('2_4', '2_3')]: if k in mesh.descs: conns = mesh.get_conn(k) break if conns is not None: nelo = conns.shape[0] output('initial mesh: %d elements' % nelo) new_conns = elems_q2t(conns) nn = new_conns.shape[0] // nelo new_cgroups = nm.repeat(mesh.cmesh.cell_groups, nn) output('new mesh: %d elements' % new_conns.shape[0]) mesh = Mesh.from_data(mesh.name, mesh.coors, mesh.cmesh.vertex_groups, [new_conns], [new_cgroups], [new_desc]) if options.merge: desc = mesh.descs[0] coor, ngroups, conns = fix_double_nodes(mesh.coors, mesh.cmesh.vertex_groups, mesh.get_conn(desc), 1e-9) mesh = Mesh.from_data(mesh.name + '_merged', coor, ngroups, [conns], [mesh.cmesh.cell_groups], [desc]) io = MeshIO.for_format(filename_out, format=options.format, writable=True) cell_types = ', '.join(supported_cell_types[io.format]) output('writing [%s] %s...' % (cell_types, filename_out)) mesh.write(filename_out, io=io) output('...done')
def refine_reference(geometry, level): """ Refine reference element given by `geometry`. Notes ----- The error edges must be generated in the order of the connectivity of the previous (lower) level. """ from sfepy.discrete.fem import Domain from sfepy.discrete.fem.geometry_element import geometry_data gcoors, gconn = geometry.coors, geometry.conn if level == 0: return gcoors, gconn gd = geometry_data[geometry.name] conn = nm.array([gd.conn], dtype=nm.int32) mat_id = conn[:, 0].copy() mat_id[:] = 0 mesh = Mesh.from_data('aux', gd.coors, None, [conn], [mat_id], [geometry.name]) domain = Domain('aux', mesh) for ii in range(level): domain = domain.refine() coors = domain.mesh.coors conn = domain.mesh.conns[0] n_el = conn.shape[0] if geometry.name == '2_3': aux_conn = conn.reshape((n_el / 4, 4, 3)) ir = [[0, 1, 2], [2, 2, 3], [3, 3, 0]] ic = [[0, 0, 0], [0, 1, 0], [0, 1, 0]] elif geometry.name == '2_4': aux_conn = conn.reshape((n_el / 4, 4, 4)) ir = [[0, 0, 1], [1, 1, 2], [2, 2, 3], [3, 3, 0], [0, 0, 2], [3, 3, 1]] ic = [[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [1, 2, 1], [1, 2, 1]] elif geometry.name == '3_4': aux_conn = conn.reshape((n_el / 8, 8, 4)) ir = [[0, 0, 1], [1, 1, 2], [2, 0, 0], [3, 1, 1], [3, 2, 2], [3, 0, 0]] ic = [[0, 1, 1], [1, 2, 2], [2, 2, 0], [3, 3, 1], [3, 3, 2], [3, 3, 0]] elif geometry.name == '3_8': aux_conn = conn.reshape((n_el / 8, 8, 8)) ir = [[0, 0, 1], [1, 1, 2], [2, 2, 3], [3, 0, 0], [0, 0, 2], [0, 0, 1], [0, 0, 1], [1, 1, 2], [2, 2, 3], [3, 0, 0], [0, 0, 2], [0, 0, 1], [4, 4, 5], [5, 5, 6], [6, 6, 7], [7, 4, 4], [4, 4, 6], [4, 4, 5], [0, 0, 4], [1, 1, 5], [2, 2, 6], [3, 3, 7], [0, 0, 4], [1, 1, 5], [2, 2, 6], [0, 0, 4], [0, 0, 4]] ic = [[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 3, 0], [1, 2, 1], [3, 2, 1], [4, 5, 4], [4, 5, 4], [4, 5, 4], [4, 7, 4], [5, 6, 5], [7, 6, 5], [0, 3, 0], [0, 3, 0], [0, 3, 0], [0, 1, 0], [3, 2, 3], [1, 2, 3], [0, 4, 0], [0, 4, 0], [0, 4, 0], [0, 4, 0], [1, 5, 3], [1, 5, 3], [1, 5, 3], [3, 7, 1], [2, 6, 2]] else: raise ValueError('unsupported geometry! (%s)' % geometry.name) conn = nm.array(conn, dtype=nm.int32) error_edges = aux_conn[:, ir, ic] return coors, conn, error_edges
def expand2d(mesh2d, dist, rep): """ Expand 2D planar mesh into 3D volume, convert triangular/quad mesh to tetrahedrons/hexahedrons. Parameters ---------- mesh2d : Mesh The 2D mesh. dist : float The elements size in the 3rd direction. rep : int The number of elements in the 3rd direction. Returns ------- mesh3d : Mesh The 3D mesh. """ if len(mesh2d.descs) > 1: raise ValueError('More than one cell type (%s). Not supported!' % ', '.join(mesh2d.descs)) nel = mesh2d.n_el nnd = mesh2d.n_nod et = mesh2d.descs[0] coors = mesh2d.coors conn = mesh2d.get_conn(et) zcoor = nm.arange(rep + 1) * dist coors3d = nm.hstack([nm.tile(coors, (rep + 1, 1)), nm.tile(zcoor, (nnd,1)).T.flatten()[:,nm.newaxis]]) ngroups = nm.tile(mesh2d.cmesh.vertex_groups, (rep + 1,)) if et == '2_4': descs3d = '3_8' conn3d = nm.zeros((nel * rep, 8), dtype=nm.int32) mats3d = nm.tile(mesh2d.cmesh.cell_groups, (1, rep)).squeeze() elif et == '2_3': descs3d = '3_4' conn3d = nm.zeros((3 * nel * rep, 4), dtype=nm.int32) mats3d = nm.tile(mesh2d.cmesh.cell_groups, (1, 3 * rep)).squeeze() for ii in range(rep): bgn0 = nnd * ii bgn1 = bgn0 + nnd if et == '2_4': bge0 = nel * ii bge1 = bge0 + nel conn3d[bge0:bge1,:4] = conn + bgn0 conn3d[bge0:bge1,4:] = conn + bgn1 elif et == '2_3': # 0 1 2 5 bge0 = 3 * nel * ii bge1 = bge0 + nel conn3d[bge0:bge1,:] = nm.array([conn[:,0] + bgn0, conn[:,1] + bgn0, conn[:,2] + bgn0, conn[:,2] + bgn1]).T # 0 1 5 4 bge0 += nel bge1 += nel conn3d[bge0:bge1,:] = nm.array([conn[:,0] + bgn0, conn[:,1] + bgn0, conn[:,2] + bgn1, conn[:,1] + bgn1]).T # 0 4 5 3 bge0 += nel bge1 += nel conn3d[bge0:bge1,:] = nm.array([conn[:,0] + bgn0, conn[:,1] + bgn1, conn[:,2] + bgn1, conn[:,0] + bgn1]).T mesh3d = Mesh.from_data('mesh', coors3d, ngroups, [conn3d], [mats3d], [descs3d]) return mesh3d
def main(): parser = ArgumentParser(description=__doc__, formatter_class=RawDescriptionHelpFormatter) parser.add_argument('-s', '--scale', metavar='scale', action='store', dest='scale', default=None, help=helps['scale']) parser.add_argument('-c', '--center', metavar='center', action='store', dest='center', default=None, help=helps['center']) parser.add_argument('-r', '--refine', metavar='level', action='store', type=int, dest='refine', default=0, help=helps['refine']) parser.add_argument('-f', '--format', metavar='format', action='store', type=str, dest='format', default=None, help=helps['format']) parser.add_argument('-l', '--list', action='store_true', dest='list', help=helps['list']) parser.add_argument('-m', '--merge', action='store_true', dest='merge', help=helps['merge']) parser.add_argument('-t', '--tri-tetra', action='store_true', dest='tri_tetra', help=helps['tri-tetra']) parser.add_argument('-2', '--2d', action='store_true', dest='force_2d', help=helps['2d']) parser.add_argument('--save-per-mat', action='store_true', dest='save_per_mat', help=helps['save-per-mat']) parser.add_argument('--remesh', metavar='options', action='store', dest='remesh', default=None, help=helps['remesh']) parser.add_argument('filename_in') parser.add_argument('filename_out') options = parser.parse_args() if options.list: output('Supported readable mesh formats:') output('--------------------------------') output_mesh_formats('r') output('') output('Supported writable mesh formats:') output('--------------------------------') output_mesh_formats('w') sys.exit(0) scale = _parse_val_or_vec(options.scale, 'scale', parser) center = _parse_val_or_vec(options.center, 'center', parser) filename_in = options.filename_in filename_out = options.filename_out if options.remesh: import tempfile import shlex import subprocess dirname = tempfile.mkdtemp() is_surface = options.remesh.startswith('q') if is_surface: mesh = Mesh.from_file(filename_in) domain = FEDomain(mesh.name, mesh) region = domain.create_region('surf', 'vertices of surface', 'facet') surf_mesh = Mesh.from_region(region, mesh, localize=True, is_surface=True) filename = op.join(dirname, 'surf.mesh') surf_mesh.write(filename, io='auto') else: import shutil shutil.copy(filename_in, dirname) filename = op.join(dirname, op.basename(filename_in)) qopts = ''.join(options.remesh.split()) # Remove spaces. command = 'tetgen -BFENkACp%s %s' % (qopts, filename) args = shlex.split(command) subprocess.call(args) root, ext = op.splitext(filename) mesh = Mesh.from_file(root + '.1.vtk') remove_files(dirname) else: mesh = Mesh.from_file(filename_in) if options.force_2d: data = list(mesh._get_io_data()) data[0] = data[0][:, :2] mesh = Mesh.from_data(mesh.name, *data) if scale is not None: if len(scale) == 1: tr = nm.eye(mesh.dim, dtype=nm.float64) * scale elif len(scale) == mesh.dim: tr = nm.diag(scale) else: raise ValueError('bad scale! (%s)' % scale) mesh.transform_coors(tr) if center is not None: cc = 0.5 * mesh.get_bounding_box().sum(0) shift = center - cc tr = nm.c_[nm.eye(mesh.dim, dtype=nm.float64), shift[:, None]] mesh.transform_coors(tr) if options.refine > 0: domain = FEDomain(mesh.name, mesh) output('initial mesh: %d nodes %d elements' % (domain.shape.n_nod, domain.shape.n_el)) for ii in range(options.refine): output('refine %d...' % ii) domain = domain.refine() output('... %d nodes %d elements' % (domain.shape.n_nod, domain.shape.n_el)) mesh = domain.mesh if options.tri_tetra > 0: mesh = triangulate(mesh, verbose=True) if options.merge: desc = mesh.descs[0] coor, ngroups, conns = fix_double_nodes(mesh.coors, mesh.cmesh.vertex_groups, mesh.get_conn(desc)) mesh = Mesh.from_data(mesh.name + '_merged', coor, ngroups, [conns], [mesh.cmesh.cell_groups], [desc]) if options.save_per_mat: desc = mesh.descs[0] conns, cgroups = mesh.get_conn(desc), mesh.cmesh.cell_groups coors, ngroups = mesh.coors, mesh.cmesh.vertex_groups mat_ids = nm.unique(cgroups) for mat_id in mat_ids: idxs = nm.where(cgroups == mat_id)[0] imesh = Mesh.from_data(mesh.name + '_matid_%d' % mat_id, coors, ngroups, [conns[idxs]], [cgroups[idxs]], [desc]) fbase, fext = op.splitext(filename_out) ifilename_out = '%s_matid_%d%s' % (fbase, mat_id, fext) io = MeshIO.for_format(ifilename_out, format=options.format, writable=True) output('writing %s...' % ifilename_out) imesh.write(ifilename_out, io=io) output('...done') io = MeshIO.for_format(filename_out, format=options.format, writable=True) cell_types = ', '.join(supported_cell_types[io.format]) output('writing [%s] %s...' % (cell_types, filename_out)) mesh.write(filename_out, io=io) output('...done')
def refine_reference(geometry, level): """ Refine reference element given by `geometry`. Notes ----- The error edges must be generated in the order of the connectivity of the previous (lower) level. """ from sfepy.discrete.fem import FEDomain from sfepy.discrete.fem.geometry_element import geometry_data gcoors, gconn = geometry.coors, geometry.conn if level == 0: return gcoors, gconn, None gd = geometry_data[geometry.name] conn = nm.array([gd.conn], dtype=nm.int32) mat_id = conn[:, 0].copy() mat_id[:] = 0 mesh = Mesh.from_data('aux', gd.coors, None, [conn], [mat_id], [geometry.name]) domain = FEDomain('aux', mesh) for ii in range(level): domain = domain.refine() coors = domain.mesh.coors conn = domain.get_conn() n_el = conn.shape[0] if geometry.name == '2_3': aux_conn = conn.reshape((n_el / 4, 4, 3)) ir = [[0, 1, 2], [2, 2, 3], [3, 3, 0]] ic = [[0, 0, 0], [0, 1, 0], [0, 1, 0]] elif geometry.name == '2_4': aux_conn = conn.reshape((n_el / 4, 4, 4)) ir = [[0, 0, 1], [1, 1, 2], [2, 2, 3], [3, 3, 0], [0, 0, 2], [3, 3, 1]] ic = [[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [1, 2, 1], [1, 2, 1]] elif geometry.name == '3_4': aux_conn = conn.reshape((n_el / 8, 8, 4)) ir = [[0, 0, 1], [1, 1, 2], [2, 0, 0], [3, 1, 1], [3, 2, 2], [3, 0, 0]] ic = [[0, 1, 1], [1, 2, 2], [2, 2, 0], [3, 3, 1], [3, 3, 2], [3, 3, 0]] elif geometry.name == '3_8': aux_conn = conn.reshape((n_el / 8, 8, 8)) ir = [[0, 0, 1], [1, 1, 2], [2, 2, 3], [3, 0, 0], [0, 0, 2], [0, 0, 1], [0, 0, 1], [1, 1, 2], [2, 2, 3], [3, 0, 0], [0, 0, 2], [0, 0, 1], [4, 4, 5], [5, 5, 6], [6, 6, 7], [7, 4, 4], [4, 4, 6], [4, 4, 5], [0, 0, 4], [1, 1, 5], [2, 2, 6], [3, 3, 7], [0, 0, 4], [1, 1, 5], [2, 2, 6], [0, 0, 4], [0, 0, 4]] ic = [[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 3, 0], [1, 2, 1], [3, 2, 1], [4, 5, 4], [4, 5, 4], [4, 5, 4], [4, 7, 4], [5, 6, 5], [7, 6, 5], [0, 3, 0], [0, 3, 0], [0, 3, 0], [0, 1, 0], [3, 2, 3], [1, 2, 3], [0, 4, 0], [0, 4, 0], [0, 4, 0], [0, 4, 0], [1, 5, 3], [1, 5, 3], [1, 5, 3], [3, 7, 1], [2, 6, 2]] else: raise ValueError('unsupported geometry! (%s)' % geometry.name) conn = nm.array(conn, dtype=nm.int32) error_edges = aux_conn[:, ir, ic] return coors, conn, error_edges
def recover_micro_hook_eps(micro_filename, region, eval_var, nodal_values, const_values, eps0, recovery_file_tag='', define_args=None, verbose=False): # Create a micro-problem instance. required, other = get_standard_keywords() required.remove('equations') conf = ProblemConf.from_file(micro_filename, required, other, verbose=False, define_args=define_args) coefs_filename = conf.options.get('coefs_filename', 'coefs') output_dir = conf.options.get('output_dir', '.') coefs_filename = op.join(output_dir, coefs_filename) + '.h5' # Coefficients and correctors coefs = Coefficients.from_file_hdf5(coefs_filename) corrs = get_correctors_from_file(dump_names=coefs.dump_names) recovery_hook = conf.options.get('recovery_hook', None) if recovery_hook is not None: recovery_hook = conf.get_function(recovery_hook) pb = Problem.from_conf(conf, init_equations=False, init_solvers=False) # Get tiling of a given region rcoors = region.domain.mesh.coors[region.get_entities(0), :] rcmin = nm.min(rcoors, axis=0) rcmax = nm.max(rcoors, axis=0) nn = nm.round((rcmax - rcmin) / eps0) if nm.prod(nn) == 0: output('inconsistency in recovery region and microstructure size!') return cs = [] for ii, n in enumerate(nn): cs.append(nm.arange(n) * eps0 + rcmin[ii]) x0 = nm.empty((int(nm.prod(nn)), nn.shape[0]), dtype=nm.float64) for ii, icoor in enumerate(nm.meshgrid(*cs, indexing='ij')): x0[:, ii] = icoor.flatten() mesh = pb.domain.mesh coors, conn, outs, ndoffset = [], [], [], 0 # Recover region mic_coors = (mesh.coors - mesh.get_bounding_box()[0, :]) * eps0 evfield = eval_var.field output('recovering microsctructures...') tt = time.clock() output_fun = output.output_function output_level = output.level for ii, c0 in enumerate(x0): local_macro = {'eps0': eps0} local_coors = mic_coors + c0 # Inside recovery region? v = nm.ones((evfield.region.entities[0].shape[0], 1)) v[evfield.vertex_remap[region.entities[0]]] = 0 no = nm.sum(v) aux = evfield.evaluate_at(local_coors, v) if (nm.sum(aux) / no) > 1e-3: continue output.level = output_level output('micro: %d' % ii) for k, v in six.iteritems(nodal_values): local_macro[k] = evfield.evaluate_at(local_coors, v) for k, v in six.iteritems(const_values): local_macro[k] = v output.set_output(quiet=not(verbose)) outs.append(recovery_hook(pb, corrs, local_macro)) output.output_function = output_fun coors.append(local_coors) conn.append(mesh.get_conn(mesh.descs[0]) + ndoffset) ndoffset += mesh.n_nod output('...done in %.2f s' % (time.clock() - tt)) # Collect output variables outvars = {} for k, v in six.iteritems(outs[0]): if v.var_name in outvars: outvars[v.var_name].append(k) else: outvars[v.var_name] = [k] # Split output by variables/regions pvs = pb.create_variables(outvars.keys()) outregs = {k: pvs[k].field.region.get_entities(-1) for k in outvars.keys()} nrve = len(coors) coors = nm.vstack(coors) ngroups = nm.tile(mesh.cmesh.vertex_groups.squeeze(), (nrve,)) conn = nm.vstack(conn) cgroups = nm.tile(mesh.cmesh.cell_groups.squeeze(), (nrve,)) # Get region mesh and data for k, cidxs in six.iteritems(outregs): gcidxs = nm.hstack([cidxs + mesh.n_el * ii for ii in range(nrve)]) rconn = conn[gcidxs] remap = -nm.ones((coors.shape[0],), dtype=nm.int32) remap[rconn] = 1 vidxs = nm.where(remap > 0)[0] remap[vidxs] = nm.arange(len(vidxs)) rconn = remap[rconn] rcoors = coors[vidxs, :] out = {} for ifield in outvars[k]: data = [outs[ii][ifield].data for ii in range(nrve)] out[ifield] = Struct(name='output_data', mode=outs[0][ifield].mode, dofs=None, var_name=k, data=nm.vstack(data)) micro_name = pb.get_output_name(extra='recovered%s_%s' % (recovery_file_tag, k)) filename = op.join(output_dir, op.basename(micro_name)) mesh_out = Mesh.from_data('recovery_%s' % k, rcoors, ngroups[vidxs], [rconn], [cgroups[gcidxs]], [mesh.descs[0]]) mesh_out.write(filename, io='auto', out=out)
def refine_3_8(mesh_in, cmesh): """ Refines hexahedral mesh by cutting cutting each edge in half and making 8 new finer hexahedrons out of one coarser one. """ # Unique edge centres. e_centres = cmesh.get_centroids(cmesh.dim - 2) # Unique face centres. f_centres = cmesh.get_centroids(cmesh.dim - 1) # Unique element centres. coors = mesh_in.get_element_coors() centres = 0.125 * nm.sum(coors, axis=1) # New coordinates after the original ones. coors = nm.r_[mesh_in.coors, e_centres, f_centres, centres] o1 = mesh_in.n_nod o2 = o1 + e_centres.shape[0] o3 = o2 + f_centres.shape[0] ecc = cmesh.get_conn(cmesh.dim, cmesh.dim - 2) eoffs = ecc.offsets fcc = cmesh.get_conn(cmesh.dim, cmesh.dim - 1) foffs = fcc.offsets st = nm.vstack conns = [] mat_ids = [] for ig, conn in enumerate(mesh_in.conns): off0, off1 = mesh_in.el_offsets[ig:ig + 2] n_el = conn.shape[0] e_nodes = ecc.indices[eoffs[off0]:eoffs[off1]].reshape((n_el, 12)) + o1 f_nodes = fcc.indices[foffs[off0]:foffs[off1]].reshape((n_el, 6)) + o2 nodes = nm.arange(n_el) + off0 + o3 c = nm.c_[conn, e_nodes, f_nodes, nodes].T new_conn = st([ c[0], c[8], c[20], c[11], c[16], c[22], c[26], c[21], c[1], c[9], c[20], c[8], c[17], c[24], c[26], c[22], c[2], c[10], c[20], c[9], c[18], c[25], c[26], c[24], c[3], c[11], c[20], c[10], c[19], c[21], c[26], c[25], c[4], c[15], c[23], c[12], c[16], c[21], c[26], c[22], c[5], c[12], c[23], c[13], c[17], c[22], c[26], c[24], c[6], c[13], c[23], c[14], c[18], c[24], c[26], c[25], c[7], c[14], c[23], c[15], c[19], c[25], c[26], c[21] ]).T new_conn = new_conn.reshape((8 * n_el, 8)) conns.append(new_conn) new_mat_id = mesh_in.mat_ids[ig].repeat(8) mat_ids.append(new_mat_id) mesh = Mesh.from_data(mesh_in.name + '_r', coors, None, conns, mat_ids, mesh_in.descs) return mesh
def _eval_basis_transform(self, subs): """ """ from sfepy.discrete import Integral from sfepy.discrete.fem import Mesh, FEDomain, Field transform = nm.tile(nm.eye(self.econn.shape[1]), (self.econn.shape[0], 1, 1)) if subs is None: return transform gel = self.gel ao = self.approx_order conn = [gel.conn] mesh = Mesh.from_data('a', gel.coors, None, [conn], [nm.array([0])], [gel.name]) cdomain = FEDomain('d', mesh) comega = cdomain.create_region('Omega', 'all') rcfield = Field.from_args('rc', self.dtype, 1, comega, approx_order=ao) fdomain = cdomain.refine() fomega = fdomain.create_region('Omega', 'all') rffield = Field.from_args('rf', self.dtype, 1, fomega, approx_order=ao) def assign_transform(transform, bf, subs, ef): if not len(subs): return n_sub = (subs.shape[1] - 2) // 2 for ii, sub in enumerate(subs): for ij in range(n_sub): ik = 2 * (ij + 1) fface = ef[sub[ik + 1]] mtx = transform[sub[ik]] ix, iy = nm.meshgrid(fface, fface) cbf = bf[iy, 0, ix] mtx[ix, iy] = cbf fcoors = rffield.get_coor() coors = fcoors[rffield.econn[0]] integral = Integral('i', coors=coors, weights=nm.ones_like(coors[:, 0])) rcfield.clear_qp_base() bf = rcfield.get_base('v', False, integral) if gel.name == '2_4': fsubs = subs esubs = None assign_transform(transform, bf, fsubs, rffield.efaces) else: fsubs = subs[0] esubs = subs[1] assign_transform(transform, bf, fsubs, rffield.efaces) if esubs is not None: assign_transform(transform, bf, esubs, rffield.eedges) assert_((nm.abs(transform.sum(1) - 1.0) < 1e-15).all()) return transform
def recover_micro_hook_eps(micro_filename, region, eval_var, nodal_values, const_values, eps0, recovery_file_tag='', define_args=None): # Create a micro-problem instance. required, other = get_standard_keywords() required.remove('equations') conf = ProblemConf.from_file(micro_filename, required, other, verbose=False, define_args=define_args) coefs_filename = conf.options.get('coefs_filename', 'coefs') output_dir = conf.options.get('output_dir', '.') coefs_filename = op.join(output_dir, coefs_filename) + '.h5' # Coefficients and correctors coefs = Coefficients.from_file_hdf5(coefs_filename) corrs = get_correctors_from_file(dump_names=coefs.dump_names) recovery_hook = conf.options.get('recovery_hook', None) if recovery_hook is not None: recovery_hook = conf.get_function(recovery_hook) pb = Problem.from_conf(conf, init_equations=False, init_solvers=False) # Get tiling of a given region rcoors = region.domain.mesh.coors[region.get_entities(0), :] rcmin = nm.min(rcoors, axis=0) rcmax = nm.max(rcoors, axis=0) nn = nm.round((rcmax - rcmin) / eps0) if nm.prod(nn) == 0: output('inconsistency in recovery region and microstructure size!') return cs = [] for ii, n in enumerate(nn): cs.append(nm.arange(n) * eps0 + rcmin[ii]) x0 = nm.empty((int(nm.prod(nn)), nn.shape[0]), dtype=nm.float64) for ii, icoor in enumerate(nm.meshgrid(*cs, indexing='ij')): x0[:, ii] = icoor.flatten() mesh = pb.domain.mesh coors, conn, outs, ndoffset = [], [], [], 0 # Recover region for ii, c0 in enumerate(x0): local_macro = {'eps0': eps0} local_coors = pb.domain.mesh.coors * eps0 + c0 # Inside recovery region? v = nm.ones((eval_var.field.region.entities[0].shape[0], 1)) v[region.entities[0]] = 0 no = nm.sum(v) aux = eval_var.field.evaluate_at(local_coors, v) if (nm.sum(aux) / no) > 1e-3: continue output('ii: %d' % ii) for k, v in six.iteritems(nodal_values): local_macro[k] = eval_var.field.evaluate_at(local_coors, v) for k, v in six.iteritems(const_values): local_macro[k] = v outs.append(recovery_hook(pb, corrs, local_macro)) coors.append(local_coors) conn.append(mesh.get_conn(mesh.descs[0]) + ndoffset) ndoffset += mesh.n_nod # Collect output variables outvars = {} for k, v in six.iteritems(outs[0]): if v.var_name in outvars: outvars[v.var_name].append(k) else: outvars[v.var_name] = [k] # Split output by variables/regions pvs = pb.create_variables(outvars.keys()) outregs = {k: pvs[k].field.region.get_entities(-1) for k in outvars.keys()} nrve = len(coors) coors = nm.vstack(coors) ngroups = nm.tile(mesh.cmesh.vertex_groups.squeeze(), (nrve,)) conn = nm.vstack(conn) cgroups = nm.tile(mesh.cmesh.cell_groups.squeeze(), (nrve,)) # Get region mesh and data for k, cidxs in six.iteritems(outregs): gcidxs = nm.hstack([cidxs + mesh.n_el * ii for ii in range(nrve)]) rconn = conn[gcidxs] remap = -nm.ones((coors.shape[0],), dtype=nm.int32) remap[rconn] = 1 vidxs = nm.where(remap > 0)[0] remap[vidxs] = nm.arange(len(vidxs)) rconn = remap[rconn] rcoors = coors[vidxs, :] out = {} for ifield in outvars[k]: data = [outs[ii][ifield].data for ii in range(nrve)] out[ifield] = Struct(name='output_data', mode=outs[0][ifield].mode, dofs=None, var_name=k, data=nm.vstack(data)) micro_name = pb.get_output_name(extra='recovered%s_%s' % (recovery_file_tag, k)) filename = op.join(output_dir, op.basename(micro_name)) mesh_out = Mesh.from_data('recovery_%s' % k, rcoors, ngroups[vidxs], [rconn], [cgroups[gcidxs]], [mesh.descs[0]]) mesh_out.write(filename, io='auto', out=out)
'output_log_name': pjoin(output_folder, f"last_run_{problem_name}_{approx_order}.txt") }) # ------------ # | Get mesh | # ------------ X1 = 0. XN = 1. n_nod = 100 n_el = n_nod - 1 coors = nm.linspace(X1, XN, n_nod).reshape((n_nod, 1)) conn = nm.arange(n_nod, dtype=nm.int32).repeat(2)[1:-1].reshape((-1, 2)) mat_ids = nm.zeros(n_nod - 1, dtype=nm.int32) descs = ['1_2'] mesh = Mesh.from_data('uniform_1D{}'.format(n_nod), coors, None, [conn], [mat_ids], descs) # ----------------------------- # | Create problem components | # ----------------------------- integral = Integral('i', order=approx_order * 2) domain = FEDomain(domain_name, mesh) omega = domain.create_region('Omega', 'all') left = domain.create_region('Gamma1', 'vertices in x == %.10f' % X1, 'vertex') right = domain.create_region('Gamma2', 'vertices in x == %.10f' % XN, 'vertex') field = DGField('dgfu', nm.float64, 'scalar', omega, approx_order=approx_order) u = FieldVariable('u', 'unknown', field, history=1) v = FieldVariable('v', 'test', field, primary_var_name='u')
# lcar3 = .055 # Assign a mesh size to all the points: gmsh.model.mesh.setSize(gmsh.model.getEntities(0), lcar1) # Override this constraint on the points of the five spheres: # gmsh.model.mesh.setSize(gmsh.model.getBoundary(holes, False, False, True), # lcar3) # Select the corner point by searching for it geometrically: # eps = 1e-3 # ov = gmsh.model.getEntitiesInBoundingBox(0.5 - eps, 0.5 - eps, 0.5 - eps, # 0.5 + eps, 0.5 + eps, 0.5 + eps, 0) # gmsh.model.mesh.setSize(ov, lcar2) gmsh.model.mesh.generate(3) gmsh.write("meshes/%s.msh" % mesh_name) gmsh.write("meshes/%s.vtk" % mesh_name) # Launch the GUI to see the results: if '-nopopup' not in sys.argv: gmsh.fltk.run() gmsh.finalize() raw_mesh = Mesh.from_file("meshes/%s.msh" % mesh_name) # load the gmesh file data = list(raw_mesh._get_io_data(cell_dim_only=[3])) # strip non-3d elements mesh = Mesh.from_data(raw_mesh.name, *data) mesh.write("meshes/%s.vtk" % mesh_name)
def main(): parser = ArgumentParser(description=__doc__, formatter_class=RawDescriptionHelpFormatter) parser.add_argument('-s', '--scale', metavar='scale', action='store', dest='scale', default=None, help=helps['scale']) parser.add_argument('-c', '--center', metavar='center', action='store', dest='center', default=None, help=helps['center']) parser.add_argument('-r', '--refine', metavar='level', action='store', type=int, dest='refine', default=0, help=helps['refine']) parser.add_argument('-f', '--format', metavar='format', action='store', type=str, dest='format', default=None, help=helps['format']) parser.add_argument('-l', '--list', action='store_true', dest='list', help=helps['list']) parser.add_argument('-m', '--merge', action='store_true', dest='merge', help=helps['merge']) parser.add_argument('-t', '--tri-tetra', action='store_true', dest='tri_tetra', help=helps['tri-tetra']) parser.add_argument('-2', '--2d', action='store_true', dest='force_2d', help=helps['2d']) parser.add_argument('--save-per-mat', action='store_true', dest='save_per_mat', help=helps['save-per-mat']) parser.add_argument('--remesh', metavar='options', action='store', dest='remesh', default=None, help=helps['remesh']) parser.add_argument('filename_in') parser.add_argument('filename_out') options = parser.parse_args() if options.list: output('Supported readable mesh formats:') output('--------------------------------') output_mesh_formats('r') output('') output('Supported writable mesh formats:') output('--------------------------------') output_mesh_formats('w') sys.exit(0) scale = _parse_val_or_vec(options.scale, 'scale', parser) center = _parse_val_or_vec(options.center, 'center', parser) filename_in = options.filename_in filename_out = options.filename_out if options.remesh: import tempfile import shlex import subprocess dirname = tempfile.mkdtemp() is_surface = options.remesh.startswith('q') if is_surface: mesh = Mesh.from_file(filename_in) domain = FEDomain(mesh.name, mesh) region = domain.create_region('surf', 'vertices of surface', 'facet') surf_mesh = Mesh.from_region(region, mesh, localize=True, is_surface=True) filename = op.join(dirname, 'surf.mesh') surf_mesh.write(filename, io='auto') else: import shutil shutil.copy(filename_in, dirname) filename = op.join(dirname, op.basename(filename_in)) qopts = ''.join(options.remesh.split()) # Remove spaces. command = 'tetgen -BFENkACp%s %s' % (qopts, filename) args = shlex.split(command) subprocess.call(args) root, ext = op.splitext(filename) mesh = Mesh.from_file(root + '.1.vtk') remove_files(dirname) else: mesh = Mesh.from_file(filename_in) if options.force_2d: data = list(mesh._get_io_data()) data[0] = data[0][:, :2] mesh = Mesh.from_data(mesh.name, *data) if scale is not None: if len(scale) == 1: tr = nm.eye(mesh.dim, dtype=nm.float64) * scale elif len(scale) == mesh.dim: tr = nm.diag(scale) else: raise ValueError('bad scale! (%s)' % scale) mesh.transform_coors(tr) if center is not None: cc = 0.5 * mesh.get_bounding_box().sum(0) shift = center - cc tr = nm.c_[nm.eye(mesh.dim, dtype=nm.float64), shift[:, None]] mesh.transform_coors(tr) if options.refine > 0: domain = FEDomain(mesh.name, mesh) output('initial mesh: %d nodes %d elements' % (domain.shape.n_nod, domain.shape.n_el)) for ii in range(options.refine): output('refine %d...' % ii) domain = domain.refine() output('... %d nodes %d elements' % (domain.shape.n_nod, domain.shape.n_el)) mesh = domain.mesh if options.tri_tetra > 0: conns = None for k, new_desc in [('3_8', '3_4'), ('2_4', '2_3')]: if k in mesh.descs: conns = mesh.get_conn(k) break if conns is not None: nelo = conns.shape[0] output('initial mesh: %d elements' % nelo) new_conns = elems_q2t(conns) nn = new_conns.shape[0] // nelo new_cgroups = nm.repeat(mesh.cmesh.cell_groups, nn) output('new mesh: %d elements' % new_conns.shape[0]) mesh = Mesh.from_data(mesh.name, mesh.coors, mesh.cmesh.vertex_groups, [new_conns], [new_cgroups], [new_desc]) if options.merge: desc = mesh.descs[0] coor, ngroups, conns = fix_double_nodes(mesh.coors, mesh.cmesh.vertex_groups, mesh.get_conn(desc), 1e-9) mesh = Mesh.from_data(mesh.name + '_merged', coor, ngroups, [conns], [mesh.cmesh.cell_groups], [desc]) if options.save_per_mat: desc = mesh.descs[0] conns, cgroups = mesh.get_conn(desc), mesh.cmesh.cell_groups coors, ngroups = mesh.coors, mesh.cmesh.vertex_groups mat_ids = nm.unique(cgroups) for mat_id in mat_ids: idxs = nm.where(cgroups == mat_id)[0] imesh = Mesh.from_data(mesh.name + '_matid_%d' % mat_id, coors, ngroups, [conns[idxs]], [cgroups[idxs]], [desc]) fbase, fext = op.splitext(filename_out) ifilename_out = '%s_matid_%d%s' % (fbase, mat_id, fext) io = MeshIO.for_format(ifilename_out, format=options.format, writable=True) output('writing %s...' % ifilename_out) imesh.write(ifilename_out, io=io) output('...done') io = MeshIO.for_format(filename_out, format=options.format, writable=True) cell_types = ', '.join(supported_cell_types[io.format]) output('writing [%s] %s...' % (cell_types, filename_out)) mesh.write(filename_out, io=io) output('...done')
def post_process_hook(pb, nd_data, qp_data, ccoor, vol, im, tstep, eps0, recovery_file_tag=''): from sfepy.discrete.fem import Mesh elavg_data = {} elvol = nm.sum(vol, axis=1) sh0 = vol.shape[:2] for k in qp_data.keys(): print(k, qp_data[k].shape, vol.shape, elvol.shape) sh1 = qp_data[k].shape[1:] val = qp_data[k].reshape(sh0 + sh1) elavg_data[k] = (nm.sum(val * vol, axis=1) / elvol)[:, None, ...] output_dir = pb.conf.options.get('output_dir', '.') suffix = '%03d.%03d' % (im, tstep) coors = pb.get_mesh_coors(actual=True) coors = (coors - 0.5*(nm.max(coors, axis=0)\ - nm.min(coors, axis=0))) * eps0 + ccoor # Y out = {} out['displacement'] = Struct(name='output_data', mode='vertex', data=nd_data['u'] * eps0, variable='u') out['green_strain'] = Struct(name='output_data', mode='cell', data=elavg_data['E']) mesh = Mesh.from_region(pb.domain.regions['Y'], pb.domain.mesh) mesh.coors[:] = coors micro_name = pb.get_output_name(extra='recovered_Y_' + recovery_file_tag + suffix) filename = osp.join(output_dir, osp.basename(micro_name)) output(' %s' % filename) mesh.write(filename, io='auto', out=out) p_tab = {'Ym': 'p', 'Yc1': 'p1', 'Yc2': 'p2'} mesh0 = pb.domain.mesh for rname in ['Ym'] + ['Yc%d' % ch for ch in pb.conf.chs]: reg = pb.domain.regions[rname] cells = reg.get_cells() out = {} out['cauchy_stress'] = Struct(name='output_data', mode='cell', data=elavg_data['S'][cells]) out['velocity'] = Struct(name='output_data', mode='cell', data=elavg_data['w'][cells]) out['pressure'] = Struct(name='output_data', mode='vertex', data=nd_data[p_tab[rname]][:, None]) ac = nm.ascontiguousarray conn = mesh0.cmesh.get_cell_conn() cells = reg.entities[-1] verts = reg.entities[0] aux = nm.diff(conn.offsets) assert nm.sum(nm.diff(aux)) == 0 conn = ac(conn.indices.reshape((mesh0.n_el, aux[0]))[cells]) remap = -nm.ones(mesh0.n_nod) remap[verts] = nm.arange(verts.shape[0]) conn = remap[conn] mesh = Mesh.from_data('region_%s' % rname, ac(coors[verts]), ac(mesh0.cmesh.vertex_groups[verts]), [conn], [ac(mesh0.cmesh.cell_groups[cells])], [mesh0.descs[0]]) micro_name = pb.get_output_name(extra='recovered_%s_' % rname + recovery_file_tag + suffix) filename = osp.join(output_dir, osp.basename(micro_name)) output(' %s' % filename) mesh.write(filename, io='auto', out=out)
def main(): parser = OptionParser(usage=usage, version='%prog') parser.add_option('-b', '--basis', metavar='name', action='store', dest='basis', default='lagrange', help=help['basis']) parser.add_option('-d', '--derivative', metavar='d', type=int, action='store', dest='derivative', default=0, help=help['derivative']) parser.add_option('-n', '--max-order', metavar='order', type=int, action='store', dest='max_order', default=2, help=help['max_order']) parser.add_option('-g', '--geometry', metavar='name', action='store', dest='geometry', default='2_4', help=help['geometry']) parser.add_option('-m', '--mesh', metavar='mesh', action='store', dest='mesh', default=None, help=help['mesh']) parser.add_option('', '--permutations', metavar='permutations', action='store', dest='permutations', default=None, help=help['permutations']) parser.add_option('', '--dofs', metavar='dofs', action='store', dest='dofs', default=None, help=help['dofs']) parser.add_option('-l', '--lin-options', metavar='options', action='store', dest='lin_options', default='min_level=2,max_level=5,eps=1e-3', help=help['lin_options']) parser.add_option('', '--plot-dofs', action='store_true', dest='plot_dofs', default=False, help=help['plot_dofs']) options, args = parser.parse_args() if len(args) == 1: output_dir = args[0] else: parser.print_help(), return output('polynomial space:', options.basis) output('max. order:', options.max_order) lin = Struct(kind='adaptive', min_level=2, max_level=5, eps=1e-3) for opt in options.lin_options.split(','): key, val = opt.split('=') setattr(lin, key, eval(val)) if options.mesh is None: dim, n_ep = int(options.geometry[0]), int(options.geometry[2]) output('reference element geometry:') output(' dimension: %d, vertices: %d' % (dim, n_ep)) gel = GeometryElement(options.geometry) gps = PolySpace.any_from_args(None, gel, 1, base=options.basis) ps = PolySpace.any_from_args(None, gel, options.max_order, base=options.basis) n_digit, _format = get_print_info(ps.n_nod, fill='0') name_template = os.path.join(output_dir, 'bf_%s.vtk' % _format) for ip in get_dofs(options.dofs, ps.n_nod): output('shape function %d...' % ip) def eval_dofs(iels, rx): if options.derivative == 0: bf = ps.eval_base(rx).squeeze() rvals = bf[None, :, ip:ip+1] else: bfg = ps.eval_base(rx, diff=True) rvals = bfg[None, ..., ip] return rvals def eval_coors(iels, rx): bf = gps.eval_base(rx).squeeze() coors = nm.dot(bf, gel.coors)[None, ...] return coors (level, coors, conn, vdofs, mat_ids) = create_output(eval_dofs, eval_coors, 1, ps, min_level=lin.min_level, max_level=lin.max_level, eps=lin.eps) out = { 'bf' : Struct(name='output_data', mode='vertex', data=vdofs, var_name='bf', dofs=None) } mesh = Mesh.from_data('bf_mesh', coors, None, [conn], [mat_ids], [options.geometry]) name = name_template % ip ensure_path(name) mesh.write(name, out=out) output('...done (%s)' % name) else: mesh = Mesh.from_file(options.mesh) output('mesh geometry:') output(' dimension: %d, vertices: %d, elements: %d' % (mesh.dim, mesh.n_nod, mesh.n_el)) if options.permutations: if options.permutations == 'all': from sfepy.linalg import cycle gel = GeometryElement(mesh.descs[0]) n_perms = gel.get_conn_permutations().shape[0] all_permutations = [ii for ii in cycle(mesh.n_el * [n_perms])] else: all_permutations = [int(ii) for ii in options.permutations.split(',')] all_permutations = nm.array(all_permutations) np = len(all_permutations) all_permutations.shape = (np / mesh.n_el, mesh.n_el) output('using connectivity permutations:\n', all_permutations) else: all_permutations = [None] for ip, permutations in enumerate(all_permutations): if permutations is None: suffix = '' else: suffix = '_' + '_'.join('%d' % ii for ii in permutations) save_basis_on_mesh(mesh, options, output_dir, lin, permutations, suffix)
def _eval_basis_transform(self, subs): """ """ from sfepy.discrete import Integral from sfepy.discrete.fem import Mesh, FEDomain, Field transform = nm.tile(nm.eye(self.econn.shape[1]), (self.econn.shape[0], 1, 1)) if subs is None: return transform gel = self.gel ao = self.approx_order conn = [gel.conn] mesh = Mesh.from_data('a', gel.coors, None, [conn], [nm.array([0])], [gel.name]) cdomain = FEDomain('d', mesh) comega = cdomain.create_region('Omega', 'all') rcfield = Field.from_args('rc', self.dtype, 1, comega, approx_order=ao) fdomain = cdomain.refine() fomega = fdomain.create_region('Omega', 'all') rffield = Field.from_args('rf', self.dtype, 1, fomega, approx_order=ao) def assign_transform(transform, bf, subs, ef): if not len(subs): return n_sub = (subs.shape[1] - 2) // 2 for ii, sub in enumerate(subs): for ij in range(n_sub): ik = 2 * (ij + 1) fface = ef[sub[ik+1]] mtx = transform[sub[ik]] ix, iy = nm.meshgrid(fface, fface) cbf = bf[iy, 0, ix] mtx[ix, iy] = cbf fcoors = rffield.get_coor() coors = fcoors[rffield.econn[0]] integral = Integral('i', coors=coors, weights=nm.ones_like(coors[:, 0])) rcfield.clear_qp_base() bf = rcfield.get_base('v', False, integral) if gel.name == '2_4': fsubs = subs esubs = None assign_transform(transform, bf, fsubs, rffield.efaces) else: fsubs = subs[0] esubs = subs[1] assign_transform(transform, bf, fsubs, rffield.efaces) if esubs is not None: assign_transform(transform, bf, esubs, rffield.eedges) assert_((nm.abs(transform.sum(1) - 1.0) < 1e-15).all()) return transform