def test_ref_coors_iga(self): from sfepy.discrete.iga.domain import IGDomain domain = IGDomain.from_file( op.join(sfepy.data_dir, 'meshes/iga/block2d.iga')) omega = domain.create_region('Omega', 'all') field = Field.from_args('iga', nm.float64, 'scalar', omega, approx_order='iga', poly_space_base='iga') mcoors = field.nurbs.cps conn = field.get_econn('volume', field.region) bbox = domain.eval_mesh.get_bounding_box() ray = nm.linspace(bbox[0, 0], bbox[1, 0], 11) coors = nm.c_[ray, ray] ref_coors, cells, status = gi.get_ref_coors(field, coors, strategy='general', close_limit=0.0, verbose=False) self.report(ref_coors) self.report(cells) self.report(status) ok = nm.all(status == 0) ctx = field.create_basis_context() for ic, cell in enumerate(cells): ctx.iel = cell bf = ctx.evaluate(ref_coors[ic:ic + 1]) cell_coors = mcoors[conn[cell]] coor = nm.dot(bf, cell_coors).ravel() _ok = nm.allclose(coor, coors[ic], atol=1e-14, rtol=0.0) if not _ok: self.report('point %d:' % ic) self.report(' - wrong reference coordinates %s!' % ref_coors[ic]) self.report(' - given point: %s' % coors[ic]) self.report(' - found point: %s' % coor) ok = ok and _ok return ok
def test_ref_coors_iga(self): from sfepy.discrete.iga.domain import IGDomain domain = IGDomain.from_file(op.join(sfepy.data_dir, 'meshes/iga/block2d.iga')) omega = domain.create_region('Omega', 'all') field = Field.from_args('iga', nm.float64, 'scalar', omega, approx_order='iga', poly_space_base='iga') mcoors = field.nurbs.cps conn = field.get_econn('volume', field.region) bbox = domain.eval_mesh.get_bounding_box() ray = nm.linspace(bbox[0, 0], bbox[1, 0], 11) coors = nm.c_[ray, ray] ref_coors, cells, status = gi.get_ref_coors(field, coors, strategy='general', close_limit=0.0, verbose=False) self.report(ref_coors) self.report(cells) self.report(status) ok = nm.all(status == 0) ctx = field.create_basis_context() for ic, cell in enumerate(cells): ctx.iel = cell bf = ctx.evaluate(ref_coors[ic:ic+1]) cell_coors = mcoors[conn[cell]] coor = nm.dot(bf, cell_coors).ravel() _ok = nm.allclose(coor, coors[ic], atol=1e-14, rtol=0.0) if not _ok: self.report('point %d:' % ic) self.report(' - wrong reference coordinates %s!' % ref_coors[ic]) self.report(' - given point: %s' % coors[ic]) self.report(' - found point: %s' % coor) ok = ok and _ok return ok
def evaluate_at(self, coors, source_vals, mode='val', strategy='general', close_limit=0.1, get_cells_fun=None, cache=None, ret_cells=False, ret_status=False, ret_ref_coors=False, verbose=False): """ Evaluate source DOF values corresponding to the field in the given coordinates using the field interpolation. Parameters ---------- coors : array, shape ``(n_coor, dim)`` The coordinates the source values should be interpolated into. source_vals : array, shape ``(n_nod, n_components)`` The source DOF values corresponding to the field. mode : {'val', 'grad'}, optional The evaluation mode: the field value (default) or the field value gradient. strategy : {'general', 'convex'}, optional The strategy for finding the elements that contain the coordinates. For convex meshes, the 'convex' strategy might be faster than the 'general' one. close_limit : float, optional The maximum limit distance of a point from the closest element allowed for extrapolation. get_cells_fun : callable, optional If given, a function with signature ``get_cells_fun(coors, cmesh, **kwargs)`` returning cells and offsets that potentially contain points with the coordinates `coors`. Applicable only when `strategy` is 'general'. When not given, :func:`get_potential_cells() <sfepy.discrete.common.global_interp.get_potential_cells>` is used. cache : Struct, optional To speed up a sequence of evaluations, the field mesh and other data can be cached. Optionally, the cache can also contain the reference element coordinates as `cache.ref_coors`, `cache.cells` and `cache.status`, if the evaluation occurs in the same coordinates repeatedly. In that case the mesh related data are ignored. See :func:`Field.get_evaluate_cache() <sfepy.discrete.fem.fields_base.FEField.get_evaluate_cache()>`. ret_ref_coors : bool, optional If True, return also the found reference element coordinates. ret_status : bool, optional If True, return also the enclosing cell status for each point. ret_cells : bool, optional If True, return also the cell indices the coordinates are in. verbose : bool If False, reduce verbosity. Returns ------- vals : array The interpolated values with shape ``(n_coor, n_components)`` or gradients with shape ``(n_coor, n_components, dim)`` according to the `mode`. If `ret_status` is False, the values where the status is greater than one are set to ``numpy.nan``. ref_coors : array The found reference element coordinates, if `ret_ref_coors` is True. cells : array The cell indices, if `ret_ref_coors` or `ret_cells` or `ret_status` are True. status : array The status, if `ret_ref_coors` or `ret_status` are True, with the following meaning: 0 is success, 1 is extrapolation within `close_limit`, 2 is extrapolation outside `close_limit`, 3 is failure, 4 is failure due to non-convergence of the Newton iteration in tensor product cells. If close_limit is 0, then for the 'general' strategy the status 5 indicates points outside of the field domain that had no potential cells. """ from sfepy.discrete.common.global_interp import get_ref_coors from sfepy.discrete.common.extmods.crefcoors import evaluate_in_rc from sfepy.base.base import complex_types output('evaluating in %d points...' % coors.shape[0], verbose=verbose) ref_coors, cells, status = get_ref_coors(self, coors, strategy=strategy, close_limit=close_limit, get_cells_fun=get_cells_fun, cache=cache, verbose=verbose) timer = Timer(start=True) # Interpolate to the reference coordinates. source_dtype = nm.float64 if source_vals.dtype in complex_types\ else source_vals.dtype if mode == 'val': vals = nm.empty((coors.shape[0], source_vals.shape[1], 1), dtype=source_dtype) cmode = 0 elif mode == 'grad': vals = nm.empty( (coors.shape[0], source_vals.shape[1], coors.shape[1]), dtype=source_dtype) cmode = 1 ctx = self.create_basis_context() if source_vals.dtype in complex_types: valsi = vals.copy() evaluate_in_rc(vals, ref_coors, cells, status, nm.ascontiguousarray(source_vals.real), self.get_econn('volume', self.region), cmode, ctx) evaluate_in_rc(valsi, ref_coors, cells, status, nm.ascontiguousarray(source_vals.imag), self.get_econn('volume', self.region), cmode, ctx) vals = vals + valsi * 1j else: evaluate_in_rc(vals, ref_coors, cells, status, source_vals, self.get_econn('volume', self.region), cmode, ctx) output('interpolation: %f s' % timer.stop(), verbose=verbose) output('...done', verbose=verbose) if mode == 'val': vals.shape = (coors.shape[0], source_vals.shape[1]) if not ret_status: ii = nm.where(status > 1)[0] vals[ii] = nm.nan if ret_ref_coors: return vals, ref_coors, cells, status elif ret_status: return vals, cells, status elif ret_cells: return vals, cells else: return vals
def _gen_common_data(orders, gels, report): import sfepy from sfepy.base.base import Struct from sfepy.linalg import combine from sfepy.discrete import FieldVariable, Integral from sfepy.discrete.fem import Mesh, FEDomain, Field from sfepy.discrete.common.global_interp import get_ref_coors bases = ([ii for ii in combine([['2_4', '3_8'], ['lagrange', 'lobatto']])] + [ii for ii in combine([['2_3', '3_4'], ['lagrange']])]) for geom, poly_space_base in bases: report('geometry: %s, base: %s' % (geom, poly_space_base)) order = orders[geom] integral = Integral('i', order=order) aux = '' if geom in ['2_4', '3_8'] else 'z' mesh0 = Mesh.from_file('meshes/elements/%s_2%s.mesh' % (geom, aux), prefix_dir=sfepy.data_dir) gel = gels[geom] perms = gel.get_conn_permutations() qps, qp_weights = integral.get_qp(gel.surface_facet.name) zz = nm.zeros_like(qps[:, :1]) qps = nm.hstack(([qps] + [zz])) shift = shifts[geom] rcoors = nm.ascontiguousarray(qps + shift[:1, :] - shift[1:, :]) ccoors = nm.ascontiguousarray(qps + shift[:1, :] + shift[1:, :]) for ir, pr in enumerate(perms): for ic, pc in enumerate(perms): report('ir: %d, ic: %d' % (ir, ic)) report('pr: %s, pc: %s' % (pr, pc)) mesh = mesh0.copy() conn = mesh.get_conn(gel.name) conn[0, :] = conn[0, pr] conn[1, :] = conn[1, pc] cache = Struct(mesh=mesh) domain = FEDomain('domain', mesh) omega = domain.create_region('Omega', 'all') region = domain.create_region('Facet', rsels[geom], 'facet') field = Field.from_args('f', nm.float64, shape=1, region=omega, approx_order=order, poly_space_base=poly_space_base) var = FieldVariable('u', 'unknown', field) report('# dofs: %d' % var.n_dof) vec = nm.empty(var.n_dof, dtype=var.dtype) ap = field.ap ps = ap.interp.poly_spaces['v'] dofs = field.get_dofs_in_region(region, merge=False) edofs, fdofs = nm.unique(dofs[1]), nm.unique(dofs[2]) rrc, rcells, rstatus = get_ref_coors(field, rcoors, cache=cache) crc, ccells, cstatus = get_ref_coors(field, ccoors, cache=cache) assert_((rstatus == 0).all() and (cstatus == 0).all()) yield (geom, poly_space_base, qp_weights, mesh, ir, ic, ap, ps, rrc, rcells[0], crc, ccells[0], vec, edofs, fdofs)
def evaluate_at(self, coors, source_vals, mode='val', strategy='general', close_limit=0.1, get_cells_fun=None, cache=None, ret_cells=False, ret_status=False, ret_ref_coors=False, verbose=False): """ Evaluate source DOF values corresponding to the field in the given coordinates using the field interpolation. Parameters ---------- coors : array, shape ``(n_coor, dim)`` The coordinates the source values should be interpolated into. source_vals : array, shape ``(n_nod, n_components)`` The source DOF values corresponding to the field. mode : {'val', 'grad'}, optional The evaluation mode: the field value (default) or the field value gradient. strategy : {'general', 'convex'}, optional The strategy for finding the elements that contain the coordinates. For convex meshes, the 'convex' strategy might be faster than the 'general' one. close_limit : float, optional The maximum limit distance of a point from the closest element allowed for extrapolation. get_cells_fun : callable, optional If given, a function with signature ``get_cells_fun(coors, cmesh, **kwargs)`` returning cells and offsets that potentially contain points with the coordinates `coors`. Applicable only when `strategy` is 'general'. When not given, :func:`get_potential_cells() <sfepy.discrete.common.global_interp.get_potential_cells>` is used. cache : Struct, optional To speed up a sequence of evaluations, the field mesh and other data can be cached. Optionally, the cache can also contain the reference element coordinates as `cache.ref_coors`, `cache.cells` and `cache.status`, if the evaluation occurs in the same coordinates repeatedly. In that case the mesh related data are ignored. See :func:`Field.get_evaluate_cache() <sfepy.discrete.fem.fields_base.FEField.get_evaluate_cache()>`. ret_ref_coors : bool, optional If True, return also the found reference element coordinates. ret_status : bool, optional If True, return also the enclosing cell status for each point. ret_cells : bool, optional If True, return also the cell indices the coordinates are in. verbose : bool If False, reduce verbosity. Returns ------- vals : array The interpolated values with shape ``(n_coor, n_components)`` or gradients with shape ``(n_coor, n_components, dim)`` according to the `mode`. If `ret_status` is False, the values where the status is greater than one are set to ``numpy.nan``. ref_coors : array The found reference element coordinates, if `ret_ref_coors` is True. cells : array The cell indices, if `ret_ref_coors` or `ret_cells` or `ret_status` are True. status : array The status, if `ret_ref_coors` or `ret_status` are True, with the following meaning: 0 is success, 1 is extrapolation within `close_limit`, 2 is extrapolation outside `close_limit`, 3 is failure, 4 is failure due to non-convergence of the Newton iteration in tensor product cells. If close_limit is 0, then for the 'general' strategy the status 5 indicates points outside of the field domain that had no potential cells. """ from sfepy.discrete.common.global_interp import get_ref_coors from sfepy.discrete.common.extmods.crefcoors import evaluate_in_rc output('evaluating in %d points...' % coors.shape[0], verbose=verbose) ref_coors, cells, status = get_ref_coors(self, coors, strategy=strategy, close_limit=close_limit, get_cells_fun=get_cells_fun, cache=cache, verbose=verbose) tt = time.clock() # Interpolate to the reference coordinates. if mode == 'val': vals = nm.empty((coors.shape[0], source_vals.shape[1], 1), dtype=source_vals.dtype) cmode = 0 elif mode == 'grad': vals = nm.empty((coors.shape[0], source_vals.shape[1], coors.shape[1]), dtype=source_vals.dtype) cmode = 1 ctx = self.create_basis_context() evaluate_in_rc(vals, ref_coors, cells, status, source_vals, self.get_econn('volume', self.region), cmode, ctx) output('interpolation: %f s' % (time.clock()-tt),verbose=verbose) output('...done',verbose=verbose) if mode == 'val': vals.shape = (coors.shape[0], source_vals.shape[1]) if not ret_status: ii = nm.where(status > 1)[0] vals[ii] = nm.nan if ret_ref_coors: return vals, ref_coors, cells, status elif ret_status: return vals, cells, status elif ret_cells: return vals, cells else: return vals
def _gen_common_data(orders, gels, report): import sfepy from sfepy.base.base import Struct from sfepy.linalg import combine from sfepy.discrete import FieldVariable, Integral from sfepy.discrete.fem import Mesh, FEDomain, Field from sfepy.discrete.common.global_interp import get_ref_coors bases = ([ii for ii in combine([['2_4', '3_8'], ['lagrange', 'lobatto']])] + [ii for ii in combine([['2_3', '3_4'], ['lagrange']])]) for geom, poly_space_base in bases: report('geometry: %s, base: %s' % (geom, poly_space_base)) order = orders[geom] integral = Integral('i', order=order) aux = '' if geom in ['2_4', '3_8'] else 'z' mesh0 = Mesh.from_file('meshes/elements/%s_2%s.mesh' % (geom, aux), prefix_dir=sfepy.data_dir) gel = gels[geom] perms = gel.get_conn_permutations() qps, qp_weights = integral.get_qp(gel.surface_facet.name) zz = nm.zeros_like(qps[:, :1]) qps = nm.hstack(([qps] + [zz])) shift = shifts[geom] rcoors = nm.ascontiguousarray(qps + shift[:1, :] - shift[1:, :]) ccoors = nm.ascontiguousarray(qps + shift[:1, :] + shift[1:, :]) for ir, pr in enumerate(perms): for ic, pc in enumerate(perms): report('ir: %d, ic: %d' % (ir, ic)) report('pr: %s, pc: %s' % (pr, pc)) mesh = mesh0.copy() conn = mesh.cmesh.get_conn(mesh0.cmesh.tdim, 0).indices conn = conn.reshape((mesh0.n_el, -1)) conn[0, :] = conn[0, pr] conn[1, :] = conn[1, pc] conn2 = mesh.get_conn(gel.name) assert_((conn == conn2).all()) cache = Struct(mesh=mesh) domain = FEDomain('domain', mesh) omega = domain.create_region('Omega', 'all') region = domain.create_region('Facet', rsels[geom], 'facet') field = Field.from_args('f', nm.float64, shape=1, region=omega, approx_order=order, poly_space_base=poly_space_base) var = FieldVariable('u', 'unknown', field) report('# dofs: %d' % var.n_dof) vec = nm.empty(var.n_dof, dtype=var.dtype) ps = field.poly_space dofs = field.get_dofs_in_region(region, merge=False) edofs, fdofs = nm.unique(dofs[1]), nm.unique(dofs[2]) rrc, rcells, rstatus = get_ref_coors(field, rcoors, cache=cache) crc, ccells, cstatus = get_ref_coors(field, ccoors, cache=cache) assert_((rstatus == 0).all() and (cstatus == 0).all()) yield (geom, poly_space_base, qp_weights, mesh, ir, ic, field, ps, rrc, rcells[0], crc, ccells[0], vec, edofs, fdofs)
def test_ref_coors_fem(self): from sfepy.discrete.fem import Mesh, FEDomain mesh = Mesh.from_file('meshes/3d/special/cross3d.mesh', prefix_dir=sfepy.data_dir) domain = FEDomain('domain', mesh) omega = domain.create_region('Omega', 'all') field = Field.from_args('linear', nm.float64, 'scalar', omega, approx_order=1) mcoors = field.domain.get_mesh_coors() conn = field.domain.get_conn() bbox = field.domain.get_mesh_bounding_box() ray = nm.linspace(bbox[0, 0], bbox[1, 0], 7) coors = nm.zeros((ray.shape[0], 3), dtype=nm.float64) def gen_rays(): coors[:, 0] = ray yield coors coors.fill(0.0) coors[:, 1] = ray yield coors coors.fill(0.0) coors[:, 2] = ray yield coors ok = True ctx = field.create_basis_context()._geo_ctx for ir, coors in enumerate(gen_rays()): self.report('ray %d' % ir) ref_coors, cells, status = gi.get_ref_coors(field, coors, strategy='general', close_limit=0.0, verbose=False) self.report(ref_coors) self.report(cells) self.report(status) # In the distorted cell 2, the Newton method finds a solution # outside of the cell. This will be fixed when box constraints # are applied. _ok = nm.all((status == 0) | ((cells == 2) & (status == 3))) if not _ok: self.report('wrong status %s for ray %d!' % (status, ir)) ok = ok and _ok for ic, cell in enumerate(cells): ctx.iel = cell bf = ctx.evaluate(ref_coors[ic:ic+1], check_errors=False) cell_coors = mcoors[conn[cell]] coor = nm.dot(bf, cell_coors).ravel() _ok = nm.allclose(coor, coors[ic], atol=1e-14, rtol=0.0) if not _ok: self.report('ray %d point %d:' % (ir, ic)) self.report(' - wrong reference coordinates %s!' % ref_coors[ic]) self.report(' - given point: %s' % coors[ic]) self.report(' - found point: %s' % coor) ok = ok and _ok return ok
def test_ref_coors_fem(self): from sfepy.discrete.fem import Mesh, FEDomain mesh = Mesh.from_file('meshes/3d/special/cross3d.mesh', prefix_dir=sfepy.data_dir) domain = FEDomain('domain', mesh) omega = domain.create_region('Omega', 'all') field = Field.from_args('linear', nm.float64, 'scalar', omega, approx_order=1) mcoors = field.domain.get_mesh_coors() conn = field.domain.get_conn() bbox = field.domain.get_mesh_bounding_box() ray = nm.linspace(bbox[0, 0], bbox[1, 0], 7) coors = nm.zeros((ray.shape[0], 3), dtype=nm.float64) def gen_rays(): coors[:, 0] = ray yield coors coors.fill(0.0) coors[:, 1] = ray yield coors coors.fill(0.0) coors[:, 2] = ray yield coors ok = True ctx = field.create_basis_context()._geo_ctx for ir, coors in enumerate(gen_rays()): self.report('ray %d' % ir) ref_coors, cells, status = gi.get_ref_coors(field, coors, strategy='general', close_limit=0.0, verbose=False) self.report(ref_coors) self.report(cells) self.report(status) # In the distorted cell 2, the Newton method finds a solution # outside of the cell. This will be fixed when box constraints # are applied. _ok = nm.all((status == 0) | ((cells == 2) & (status == 3))) if not _ok: self.report('wrong status %s for ray %d!' % (status, ir)) ok = ok and _ok for ic, cell in enumerate(cells): ctx.iel = cell bf = ctx.evaluate(ref_coors[ic:ic + 1], check_errors=False) cell_coors = mcoors[conn[cell]] coor = nm.dot(bf, cell_coors).ravel() _ok = nm.allclose(coor, coors[ic], atol=1e-14, rtol=0.0) if not _ok: self.report('ray %d point %d:' % (ir, ic)) self.report(' - wrong reference coordinates %s!' % ref_coors[ic]) self.report(' - given point: %s' % coors[ic]) self.report(' - found point: %s' % coor) ok = ok and _ok return ok