Example #1
0
    def describe_membrane_geometry(self, ig, field, sg, sd):
        # Coordinates of element vertices.
        coors = field.coors[sd.econn[:, :sg.n_fp]]

        # Coordinate transformation matrix (transposed!).
        self.mtx_t[ig] = membranes.create_transformation_matrix(coors)

        # Transform coordinates to the local coordinate system.
        coors_loc = dot_sequences((coors - coors[:, 0:1, :]), self.mtx_t[ig])

        # Mapping from transformed element to reference element.
        gel = field.gel.surface_facet
        vm = membranes.create_mapping(coors_loc, gel, 1)

        qp = self.integral.get_qp(gel.name)
        ps = PolySpace.any_from_args(None, gel, field.approx_order)
        self.membrane_geo[ig] = vm.get_mapping(qp[0], qp[1], poly_space=ps)

        # Transformed base function gradient w.r.t. material coordinates
        # in quadrature points.
        self.bfg[ig] = self.membrane_geo[ig].bfg
Example #2
0
File: fea.py Project: LeiDai/sfepy
    def describe_geometry(self, field, gtype, region, integral,
                          return_mapping=False):
        """
        Compute jacobians, element volumes and base function derivatives
        for Volume-type geometries (volume mappings), and jacobians,
        normals and base function derivatives for Surface-type
        geometries (surface mappings).

        Notes
        -----
        - volume mappings can be defined on a part of an element group,
          although the field has to be defined always on the whole group.
        - surface mappings are defined on the surface region
        - surface mappings require field order to be > 0
        """
        domain = field.domain
        group = domain.groups[self.ig]
        coors = domain.get_mesh_coors(actual=True)

        if gtype == 'volume':
            qp = self.get_qp('v', integral)

            iels = region.get_cells(self.ig)

            geo_ps = self.interp.get_geom_poly_space('v')
            ps = self.interp.poly_spaces['v']
            bf = self.get_base('v', 0, integral, iels=iels)

            conn = nm.take(group.conn, iels.astype(nm.int32), axis=0)
            mapping = VolumeMapping(coors, conn, poly_space=geo_ps)
            vg = mapping.get_mapping(qp.vals, qp.weights, poly_space=ps,
                                     ori=self.ori)

            out = vg

        elif gtype == 'plate':
            import sfepy.mechanics.membranes as mm
            from sfepy.linalg import dot_sequences

            qp = self.get_qp('v', integral)
            iels = region.get_cells(self.ig)

            ps = self.interp.poly_spaces['v']
            bf = self.get_base('v', 0, integral, iels=iels)

            conn = nm.take(group.conn, nm.int32(iels), axis=0)
            ccoors = coors[conn]

            # Coordinate transformation matrix (transposed!).
            mtx_t = mm.create_transformation_matrix(ccoors)

            # Transform coordinates to the local coordinate system.
            coors_loc = dot_sequences((ccoors - ccoors[:, 0:1, :]), mtx_t)

            # Mapping from transformed elements to reference elements.
            mapping = mm.create_mapping(coors_loc, field.gel, 1)
            vg = mapping.get_mapping(qp.vals, qp.weights, poly_space=ps,
                                     ori=self.ori)
            vg.mtx_t = mtx_t
            out = vg

        elif (gtype == 'surface') or (gtype == 'surface_extra'):
            assert_(field.approx_order > 0)

            if self.ori is not None:
                msg = 'surface integrals do not work yet with the' \
                      ' hierarchical basis!'
                raise ValueError(msg)

            sd = domain.surface_groups[self.ig][region.name]
            esd = self.surface_data[region.name]

            qp = self.get_qp(sd.face_type, integral)

            geo_ps = self.interp.get_geom_poly_space(sd.face_type)
            ps = self.interp.poly_spaces[esd.face_type]
            bf = self.get_base(esd.face_type, 0, integral)

            conn = sd.get_connectivity()

            mapping = SurfaceMapping(coors, conn, poly_space=geo_ps)
            sg = mapping.get_mapping(qp.vals, qp.weights, poly_space=ps,
                                     mode=gtype)
            if gtype == 'surface_extra':
                sg.alloc_extra_data(self.n_ep['v'])

                self.create_bqp(region.name, integral)
                qp = self.qp_coors[(integral.name, esd.bkey)]

                v_geo_ps = self.interp.get_geom_poly_space('v')
                bf_bg = v_geo_ps.eval_base(qp.vals, diff=True)
                ebf_bg = self.get_base(esd.bkey, 1, integral)

                sg.evaluate_bfbgm(bf_bg, ebf_bg, coors, sd.fis, group.conn)

            out =  sg

        elif gtype == 'point':
            out = mapping = None

        else:
            raise ValueError('unknown geometry type: %s' % gtype)

        if out is not None:
            # Store the integral used.
            out.integral = integral
            out.qp = qp
            out.ps = ps
            # Update base.
            out.bf[:] = bf

        if return_mapping:
            out = (out, mapping)

        return out
Example #3
0
    def create_mapping(self, region, integral, integration,
                       return_mapping=True):
        """
        Create a new reference mapping.

        Compute jacobians, element volumes and base function derivatives
        for Volume-type geometries (volume mappings), and jacobians,
        normals and base function derivatives for Surface-type
        geometries (surface mappings).

        Notes
        -----
        - surface mappings are defined on the surface region
        - surface mappings require field order to be > 0
        """
        domain = self.domain
        coors = domain.get_mesh_coors(actual=True)
        dconn = domain.get_conn()

        if integration == 'volume':
            qp = self.get_qp('v', integral)

            iels = region.get_cells()

            geo_ps = self.gel.poly_space
            ps = self.poly_space
            bf = self.get_base('v', 0, integral, iels=iels)

            conn = nm.take(dconn, iels.astype(nm.int32), axis=0)
            mapping = VolumeMapping(coors, conn, poly_space=geo_ps)
            vg = mapping.get_mapping(qp.vals, qp.weights, poly_space=ps,
                                     ori=self.ori)

            out = vg

        elif integration == 'plate':
            import sfepy.mechanics.membranes as mm
            from sfepy.linalg import dot_sequences

            qp = self.get_qp('v', integral)
            iels = region.get_cells()

            ps = self.interp.poly_spaces['v']
            bf = self.get_base('v', 0, integral, iels=iels)

            conn = nm.take(dconn, nm.int32(iels), axis=0)
            ccoors = coors[conn]

            # Coordinate transformation matrix (transposed!).
            mtx_t = mm.create_transformation_matrix(ccoors)

            # Transform coordinates to the local coordinate system.
            coors_loc = dot_sequences((ccoors - ccoors[:, 0:1, :]), mtx_t)

            # Mapping from transformed elements to reference elements.
            mapping = mm.create_mapping(coors_loc, self.gel, 1)
            vg = mapping.get_mapping(qp.vals, qp.weights, poly_space=ps,
                                     ori=self.ori)
            vg.mtx_t = mtx_t
            out = vg

        elif (integration == 'surface') or (integration == 'surface_extra'):
            assert_(self.approx_order > 0)

            if self.ori is not None:
                msg = 'surface integrals do not work yet with the' \
                      ' hierarchical basis!'
                raise ValueError(msg)

            sd = domain.surface_groups[region.name]
            esd = self.surface_data[region.name]

            geo_ps = self.gel.poly_space
            ps = self.poly_space

            conn = sd.get_connectivity()
            mapping = SurfaceMapping(coors, conn, poly_space=geo_ps)

            if not self.is_surface:
                self.create_bqp(region.name, integral)
                qp = self.qp_coors[(integral.order, esd.bkey)]

                abf = ps.eval_base(qp.vals[0])
                bf = abf[..., self.efaces[0]]

                indx = self.gel.get_surface_entities()[0]
                # Fix geometry element's 1st facet orientation for gradients.
                indx = nm.roll(indx, -1)[::-1]
                mapping.set_basis_indices(indx)

                sg = mapping.get_mapping(qp.vals[0], qp.weights,
                                         poly_space=Struct(n_nod=bf.shape[-1]),
                                         mode=integration)

                if integration == 'surface_extra':
                    sg.alloc_extra_data(self.econn.shape[1])

                    bf_bg = geo_ps.eval_base(qp.vals, diff=True)
                    ebf_bg = self.get_base(esd.bkey, 1, integral)

                    sg.evaluate_bfbgm(bf_bg, ebf_bg, coors, sd.fis, dconn)

            else:
                # Do not use BQP for surface fields.
                qp = self.get_qp(sd.face_type, integral)
                bf = ps.eval_base(qp.vals)

                sg = mapping.get_mapping(qp.vals, qp.weights,
                                         poly_space=Struct(n_nod=bf.shape[-1]),
                                         mode=integration)

            out =  sg

        elif integration == 'point':
            out = mapping = None

        else:
            raise ValueError('unknown inegration geometry type: %s'
                             % integration)

        if out is not None:
            # Store the integral used.
            out.integral = integral
            out.qp = qp
            out.ps = ps
            # Update base.
            out.bf[:] = bf

        if return_mapping:
            out = (out, mapping)

        return out
Example #4
0
    def describe_geometry(self,
                          field,
                          gtype,
                          region,
                          integral,
                          return_mapping=False):
        """
        Compute jacobians, element volumes and base function derivatives
        for Volume-type geometries (volume mappings), and jacobians,
        normals and base function derivatives for Surface-type
        geometries (surface mappings).

        Notes
        -----
        - volume mappings can be defined on a part of an element group,
          although the field has to be defined always on the whole group.
        - surface mappings are defined on the surface region
        - surface mappings require field order to be > 0
        """
        domain = field.domain
        group = domain.groups[self.ig]
        coors = domain.get_mesh_coors(actual=True)

        if gtype == 'volume':
            qp = self.get_qp('v', integral)

            iels = region.get_cells(self.ig)

            geo_ps = self.interp.get_geom_poly_space('v')
            ps = self.interp.poly_spaces['v']
            bf = self.get_base('v', 0, integral, iels=iels)

            conn = nm.take(group.conn, iels.astype(nm.int32), axis=0)
            mapping = VolumeMapping(coors, conn, poly_space=geo_ps)
            vg = mapping.get_mapping(qp.vals,
                                     qp.weights,
                                     poly_space=ps,
                                     ori=self.ori)

            out = vg

        elif gtype == 'plate':
            import sfepy.mechanics.membranes as mm
            from sfepy.linalg import dot_sequences

            qp = self.get_qp('v', integral)
            iels = region.get_cells(self.ig)

            ps = self.interp.poly_spaces['v']
            bf = self.get_base('v', 0, integral, iels=iels)

            conn = nm.take(group.conn, nm.int32(iels), axis=0)
            ccoors = coors[conn]

            # Coordinate transformation matrix (transposed!).
            mtx_t = mm.create_transformation_matrix(ccoors)

            # Transform coordinates to the local coordinate system.
            coors_loc = dot_sequences((ccoors - ccoors[:, 0:1, :]), mtx_t)

            # Mapping from transformed elements to reference elements.
            mapping = mm.create_mapping(coors_loc, field.gel, 1)
            vg = mapping.get_mapping(qp.vals,
                                     qp.weights,
                                     poly_space=ps,
                                     ori=self.ori)
            vg.mtx_t = mtx_t
            out = vg

        elif (gtype == 'surface') or (gtype == 'surface_extra'):
            assert_(field.approx_order > 0)

            if self.ori is not None:
                msg = 'surface integrals do not work yet with the' \
                      ' hierarchical basis!'
                raise ValueError(msg)

            sd = domain.surface_groups[self.ig][region.name]
            esd = self.surface_data[region.name]

            qp = self.get_qp(sd.face_type, integral)

            geo_ps = self.interp.get_geom_poly_space(sd.face_type)
            ps = self.interp.poly_spaces[esd.face_type]
            bf = self.get_base(esd.face_type, 0, integral)

            conn = sd.get_connectivity()

            mapping = SurfaceMapping(coors, conn, poly_space=geo_ps)
            sg = mapping.get_mapping(qp.vals,
                                     qp.weights,
                                     poly_space=ps,
                                     mode=gtype)
            if gtype == 'surface_extra':
                sg.alloc_extra_data(self.n_ep['v'])

                self.create_bqp(region.name, integral)
                qp = self.qp_coors[(integral.order, esd.bkey)]

                v_geo_ps = self.interp.get_geom_poly_space('v')
                bf_bg = v_geo_ps.eval_base(qp.vals, diff=True)
                ebf_bg = self.get_base(esd.bkey, 1, integral)

                sg.evaluate_bfbgm(bf_bg, ebf_bg, coors, sd.fis, group.conn)

            out = sg

        elif gtype == 'point':
            out = mapping = None

        else:
            raise ValueError('unknown geometry type: %s' % gtype)

        if out is not None:
            # Store the integral used.
            out.integral = integral
            out.qp = qp
            out.ps = ps
            # Update base.
            out.bf[:] = bf

        if return_mapping:
            out = (out, mapping)

        return out
Example #5
0
    def create_mapping(self,
                       region,
                       integral,
                       integration,
                       return_mapping=True):
        """
        Create a new reference mapping.

        Compute jacobians, element volumes and base function derivatives
        for Volume-type geometries (volume mappings), and jacobians,
        normals and base function derivatives for Surface-type
        geometries (surface mappings).

        Notes
        -----
        - surface mappings are defined on the surface region
        - surface mappings require field order to be > 0
        """
        domain = self.domain
        coors = domain.get_mesh_coors(actual=True)
        dconn = domain.get_conn()

        if integration == 'volume':
            qp = self.get_qp('v', integral)

            iels = region.get_cells()

            geo_ps = self.gel.poly_space
            ps = self.poly_space
            bf = self.get_base('v', 0, integral, iels=iels)

            conn = nm.take(dconn, iels.astype(nm.int32), axis=0)
            mapping = VolumeMapping(coors, conn, poly_space=geo_ps)
            vg = mapping.get_mapping(qp.vals,
                                     qp.weights,
                                     poly_space=ps,
                                     ori=self.ori)

            out = vg

        elif integration == 'plate':
            import sfepy.mechanics.membranes as mm
            from sfepy.linalg import dot_sequences

            qp = self.get_qp('v', integral)
            iels = region.get_cells()

            ps = self.interp.poly_spaces['v']
            bf = self.get_base('v', 0, integral, iels=iels)

            conn = nm.take(dconn, nm.int32(iels), axis=0)
            ccoors = coors[conn]

            # Coordinate transformation matrix (transposed!).
            mtx_t = mm.create_transformation_matrix(ccoors)

            # Transform coordinates to the local coordinate system.
            coors_loc = dot_sequences((ccoors - ccoors[:, 0:1, :]), mtx_t)

            # Mapping from transformed elements to reference elements.
            mapping = mm.create_mapping(coors_loc, self.gel, 1)
            vg = mapping.get_mapping(qp.vals,
                                     qp.weights,
                                     poly_space=ps,
                                     ori=self.ori)
            vg.mtx_t = mtx_t
            out = vg

        elif (integration == 'surface') or (integration == 'surface_extra'):
            assert_(self.approx_order > 0)

            if self.ori is not None:
                msg = 'surface integrals do not work yet with the' \
                      ' hierarchical basis!'
                raise ValueError(msg)

            sd = domain.surface_groups[region.name]
            esd = self.surface_data[region.name]

            geo_ps = self.gel.poly_space
            ps = self.poly_space

            conn = sd.get_connectivity()
            mapping = SurfaceMapping(coors, conn, poly_space=geo_ps)

            if not self.is_surface:
                self.create_bqp(region.name, integral)
                qp = self.qp_coors[(integral.order, esd.bkey)]

                abf = ps.eval_base(qp.vals[0])
                bf = abf[..., self.efaces[0]]

                indx = self.gel.get_surface_entities()[0]
                # Fix geometry element's 1st facet orientation for gradients.
                indx = nm.roll(indx, -1)[::-1]
                mapping.set_basis_indices(indx)

                sg = mapping.get_mapping(qp.vals[0],
                                         qp.weights,
                                         poly_space=Struct(n_nod=bf.shape[-1]),
                                         mode=integration)

                if integration == 'surface_extra':
                    sg.alloc_extra_data(self.econn.shape[1])

                    bf_bg = geo_ps.eval_base(qp.vals, diff=True)
                    ebf_bg = self.get_base(esd.bkey, 1, integral)

                    sg.evaluate_bfbgm(bf_bg, ebf_bg, coors, sd.fis, dconn)

            else:
                # Do not use BQP for surface fields.
                qp = self.get_qp(sd.face_type, integral)
                bf = ps.eval_base(qp.vals)

                sg = mapping.get_mapping(qp.vals,
                                         qp.weights,
                                         poly_space=Struct(n_nod=bf.shape[-1]),
                                         mode=integration)

            out = sg

        elif integration == 'point':
            out = mapping = None

        else:
            raise ValueError('unknown inegration geometry type: %s' %
                             integration)

        if out is not None:
            # Store the integral used.
            out.integral = integral
            out.qp = qp
            out.ps = ps
            # Update base.
            out.bf[:] = bf

        if return_mapping:
            out = (out, mapping)

        return out