Пример #1
0
    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
Пример #2
0
    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
Пример #3
0
    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
Пример #4
0
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)
Пример #5
0
    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
Пример #6
0
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)
Пример #7
0
    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
Пример #8
0
    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