def get_volume(el, nd): from sfepy.mesh.mesh_tools import elems_q2t from sfepy.base.compat import factorial import numpy as nm from sfepy.linalg.utils import dets_fast dim = nd.shape[1] nnd = el.shape[1] etype = '%d_%d' % (dim, nnd) if etype == '2_4' or etype == '3_8': el = elems_q2t(el) nel = el.shape[0] mul = 1.0 / factorial(dim) if dim == 3: mul *= -1.0 mtx = nm.ones((nel, dim + 1, dim + 1), dtype=nm.double) mtx[:, :, :-1] = nd[el, :] vols = mul * dets_fast(mtx.copy()) vol = vols.sum() return vol
def get_volume(el, nd): from sfepy.mesh.mesh_tools import elems_q2t from sfepy.base.compat import factorial import numpy as nm from sfepy.linalg.utils import dets_fast dim = nd.shape[1] nnd = el.shape[1] etype = '%d_%d' % (dim, nnd) if etype == '2_4' or etype == '3_8': el = elems_q2t(el) nel = el.shape[0] mul = 1.0 / factorial(dim) if dim == 3: mul *= -1.0 mtx = nm.ones((nel, dim + 1, dim + 1), dtype=nm.double) mtx[:,:,:-1] = nd[el,:] vols = mul * dets_fast(mtx.copy()) vol = vols.sum() return vol
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 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 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 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')