def plot_basis(self, p=2, q=20, plot=True):
        node = np.array([
            (0.0, 0.0), (1.0, 0.0), (0.5, np.sqrt(3)/2)], dtype=np.float)
        cell = np.array([(0, 1, 2)], dtype=np.int)
        mesh = TriangleMesh(node, cell)
        space = LagrangeFiniteElementSpace(mesh, p=p)

        bc = space.multi_index_matrix[1](q)/q
        node = mesh.bc_to_point(bc) #( NQ, 1, 2)
        phi = space.basis(bc) # (NQ, 1, ldof)

        fig = plt.figure()
        axes = fig.gca(projection='3d')
        axes.plot_trisurf(
                node[..., 0].reshape(-1), 
                node[..., 1].reshape(-1), 
                phi[..., 0].reshape(-1),
                cmap='rainbow', lw=0.0, antialiased=True)
        axes.plot_trisurf(
                node[..., 0].reshape(-1), 
                node[..., 1].reshape(-1), 
                phi[..., 1].reshape(-1),
                cmap='rainbow', lw=0.0, antialiased=True)
        plt.show()
示例#2
0
class SurfaceTriangleMesh():
    def __init__(self, mesh, surface, p=1, scale=None):
        """
        Initial a object of Surface Triangle Mesh.

        Parameters
        ----------
        self :
            Surface Triangle Mesh Object
        mesh :
            mesh object, represents a triangulation with flat triangle faces.
        surface :
            The continuous surface which was represented as a level set
            function.
        p : int
            The degree of the Lagrange space

        Returns
        -------

        See Also
        --------

        Notes
        -----
        """
        self.mesh = mesh
        self.p = p
        self.space = LagrangeFiniteElementSpace(mesh, p)
        self.surface = surface
        self.ds = mesh.ds
        self.scale = scale
        if scale is not None:
            self.mesh.node *= scale

        if scale is None:
            self.node, d = self.surface.project(
                self.space.interpolation_points())
        else:
            self.node, d = self.surface.project(
                self.space.interpolation_points() / scale)
            self.node *= scale

        self.meshtype = 'stri'
        self.ftype = mesh.ftype
        self.itype = mesh.itype
        self.nodedata = {}
        self.celldata = {}

    def vtk_cell_type(self):
        return 69

    def project(self, p):
        if self.scale is None:
            return self.surface.project(p)
        else:
            p, d = self.surface.project(p / self.scale)
            return p * self.scale, d * self.scale

    def integrator(self, k, etype='cell'):
        return TriangleQuadrature(k)

    def entity(self, etype=2):
        if etype in {'cell', 2}:
            return self.ds.cell
        elif etype in {'edge', 1}:
            return self.ds.edge
        elif etype in {'node', 0}:
            return self.mesh.node
        else:
            raise ValueError("`entitytype` is wrong!")

    def entity_measure(self, etype=2):
        p = self.p
        if etype in {'cell', 2}:
            return self.area(p + 1)
        elif etype in {'edge', 'face', 1}:
            return self.mesh.entity_measure('edge')
        else:
            raise ValueError("`entitytype` is wrong!")

    def entity_barycenter(self, etype=2):
        p = self.p
        return self.mesh.entity_barycenter(etype=etype)

    def number_of_nodes(self):
        return self.node.shape[0]

    def number_of_edges(self):
        return self.mesh.ds.NE

    def number_of_cells(self):
        return self.mesh.ds.NC

    def geo_dimension(self):
        return self.node.shape[1]

    def top_dimension(self):
        return 2

    def jacobi_matrix(self, bc, index=np.s_[:]):
        mesh = self.mesh
        cell2dof = self.space.dof.cell2dof

        grad = self.space.grad_basis(bc, index=index)
        # the tranpose of the jacobi matrix between S_h and K
        Jh = mesh.jacobi_matrix(index=index)

        # the tranpose of the jacobi matrix between S_p and S_h
        Jph = np.einsum('ijm, ...ijk->...imk', self.node[cell2dof[index], :],
                        grad)

        # the transpose of the jacobi matrix between S_p and K
        Jp = np.einsum('...ijk, imk->...imj', Jph, Jh)
        grad = np.einsum('ijk, ...imk->...imj', Jh, grad)
        return Jp, grad

    def normal(self, bc, index=None):
        Js, _, ps = self.surface_jacobi_matrix(bc, index=index)
        n = np.cross(Js[..., 0, :], Js[..., 1, :], axis=-1)
        return n, ps

    def surface_jacobi_matrix(self, bc, index=None):
        Jp, grad = self.jacobi_matrix(bc, index=index)
        ps = self.bc_to_point(bc, index=index)
        Jsp = self.surface.jacobi_matrix(ps)
        Js = np.einsum('...ijk, ...imk->...imj', Jsp, Jp)
        return Js, grad, ps

    def bc_to_point(self, bc, index=None):
        phi = self.space.basis(bc)
        cell2dof = self.space.dof.cell2dof
        if index is None:
            bcp = np.einsum('...ij, ijk->...ik', phi, self.node[cell2dof, :])
        else:
            bcp = np.einsum('...ij, ijk->...ik', phi,
                            self.node[cell2dof[index], :])

        bcp, _ = self.project(bcp)
        return bcp

    def area(self, q=3):
        integrator = self.integrator(q)
        bcs, ws = integrator.quadpts, integrator.weights
        Jp, _ = self.jacobi_matrix(bcs)
        n = np.cross(Jp[..., 0, :], Jp[..., 1, :], axis=-1)
        l = np.sqrt(np.sum(n**2, axis=-1))
        a = np.einsum('i, ij->j', ws, l) / 2.0
        return a

    def add_plot(self,
                 plot,
                 nodecolor='w',
                 edgecolor='k',
                 cellcolor=[0.5, 0.9, 0.45],
                 aspect='equal',
                 linewidths=1,
                 markersize=50,
                 showaxis=False,
                 showcolorbar=False,
                 cmap='rainbow'):

        if isinstance(plot, ModuleType):
            fig = plot.figure()
            fig.set_facecolor('white')
            axes = fig.gca()
        else:
            axes = plot
        return show_mesh_2d(axes,
                            self.mesh,
                            nodecolor=nodecolor,
                            edgecolor=edgecolor,
                            cellcolor=cellcolor,
                            aspect=aspect,
                            linewidths=linewidths,
                            markersize=markersize,
                            showaxis=showaxis,
                            showcolorbar=showcolorbar,
                            cmap=cmap)

    def find_node(self,
                  axes,
                  node=None,
                  index=None,
                  showindex=False,
                  color='r',
                  markersize=100,
                  fontsize=24,
                  fontcolor='k'):

        if node is None:
            node = self.node

        if (index is None) and (showindex is True):
            index = np.array(range(node.shape[0]))

        find_node(axes,
                  node,
                  index=index,
                  showindex=showindex,
                  color=color,
                  markersize=markersize,
                  fontsize=fontsize,
                  fontcolor=fontcolor)

    def find_edge(self,
                  axes,
                  index=None,
                  showindex=False,
                  color='g',
                  markersize=150,
                  fontsize=24,
                  fontcolor='k'):

        find_entity(axes,
                    self.mesh,
                    entity='edge',
                    index=index,
                    showindex=showindex,
                    color=color,
                    markersize=markersize,
                    fontsize=fontsize,
                    fontcolor=fontcolor)

    def find_cell(self,
                  axes,
                  index=None,
                  showindex=False,
                  color='y',
                  markersize=200,
                  fontsize=24,
                  fontcolor='k'):

        find_entity(axes,
                    self.mesh,
                    entity='cell',
                    index=index,
                    showindex=showindex,
                    color=color,
                    markersize=markersize,
                    fontsize=fontsize,
                    fontcolor=fontcolor)
示例#3
0
import numpy as np
import matplotlib.pyplot as plt

from fealpy.functionspace import LagrangeFiniteElementSpace
from fealpy.pde.poisson_1d import CosData

n = 100
p = 4

pde = CosData()
mesh = pde.init_mesh(n=0)

bc = np.zeros((n, 2), dtype=np.float)
bc[:, 1] = np.linspace(0, 1, n)
bc[:, 0] = 1 - bc[:, 1]

space = LagrangeFiniteElementSpace(mesh, p=p)

val = space.basis(bc)
print(val.shape)

fig = plt.figure()
axes = fig.gca()
mesh.add_plot(axes)
axes.plot(bc[:, 1], val)
axes.set_axis_on()
plt.show()
示例#4
0
class HuZhangFiniteElementSpace():
    """
    Hu-Zhang Mixed Finite Element Space.
    """
    def __init__(self, mesh, p):
        self.space = LagrangeFiniteElementSpace(mesh, p)  # the scalar space
        self.mesh = mesh
        self.p = p
        self.dof = self.space.dof
        self.dim = self.space.GD
        self.init_orth_matrices()
        self.init_cell_to_dof()

    def init_orth_matrices(self):
        """
        Initialize the othogonal symetric matrix basis.
        """
        mesh = self.mesh
        gdim = self.geo_dimension()

        NE = mesh.number_of_edges()
        if gdim == 2:
            idx = np.array([(0, 0), (1, 1), (0, 1)])
            self.TE = np.zeros((NE, 3, 3), dtype=np.float)
            self.T = np.array([[(1, 0), (0, 0)], [(0, 0), (0, 1)],
                               [(0, 1), (1, 0)]])
        elif gdim == 3:
            idx = np.array([(0, 0), (1, 1), (2, 2), (1, 2), (0, 2), (0, 1)])
            self.TE = np.zeros((NE, 6, 6), dtype=np.float)
            self.T = np.array([[(1, 0, 0), (0, 0, 0), (0, 0, 0)],
                               [(0, 0, 0), (0, 1, 0), (0, 0, 0)],
                               [(0, 0, 0), (0, 0, 0), (0, 0, 1)],
                               [(0, 0, 0), (0, 0, 1), (0, 1, 0)],
                               [(0, 0, 1), (0, 0, 0), (1, 0, 0)],
                               [(0, 1, 0), (1, 0, 0), (0, 0, 0)]])

        t = mesh.edge_unit_tagent()
        _, _, frame = np.linalg.svd(
            t[:, np.newaxis, :])  # get the axis frame on the edge by svd
        frame[:, 0, :] = t
        for i, (j, k) in enumerate(idx):
            self.TE[:,
                    i] = (frame[:, j, idx[:, 0]] * frame[:, k, idx[:, 1]] +
                          frame[:, j, idx[:, 1]] * frame[:, k, idx[:, 0]]) / 2
        self.TE[:, gdim:] *= np.sqrt(2)

        if gdim == 3:
            NF = mesh.number_of_faces()
            self.TF = np.zeros((NF, 6, 6), dtype=np.float)
            n = mesh.face_unit_normal()
            _, _, frame = np.linalg.svd(
                n[:, np.newaxis, :])  # get the axis frame on the edge by svd
            frame[:, 0, :] = n
            for i, (j, k) in enumerate(idx):
                self.TF[:, i] = (
                    frame[:, j, idx[:, 0]] * frame[:, k, idx[:, 1]] +
                    frame[:, j, idx[:, 1]] * frame[:, k, idx[:, 0]]) / 2

            self.TF[:, gdim:] *= np.sqrt(2)

    def __str__(self):
        return "Hu-Zhang mixed finite element space!"

    def number_of_global_dofs(self):
        """
        """
        p = self.p
        gdim = self.geo_dimension()
        tdim = self.tensor_dimension()

        mesh = self.mesh

        NC = mesh.number_of_cells()
        NN = mesh.number_of_nodes()
        gdof = tdim * NN

        if p > 1:
            edof = p - 1
            NE = mesh.number_of_edges()
            gdof += (tdim - 1) * edof * NE  # 边内部连续自由度的个数
            E = mesh.number_of_edges_of_cells()  # 单元边的个数
            gdof += NC * E * edof  # 边内部不连续自由度的个数

        if p > 2:
            fdof = (p + 1) * (p + 2) // 2 - 3 * p  # 面内部自由度的个数
            if gdim == 2:
                gdof += tdim * fdof * NC
            elif gdim == 3:
                NF = mesh.number_of_faces()
                gdof += 3 * fdof * NF  # 面内部连续自由度的个数
                F = mesh.number_of_faces_of_cells()  # 每个单元面的个数
                gdof += 3 * F * fdof * NC  # 面内部不连续自由度的个数

        if (p > 3) and (gdim == 3):
            ldof = self.dof.number_of_local_dofs()
            V = mesh.number_of_nodes_of_cells()  # 单元顶点的个数
            cdof = ldof - E * edof - F * fdof - V
            gdof += tdim * cdof * NC
        return gdof

    def number_of_local_dofs(self):
        tdim = self.tensor_dimension()
        ldof = self.dof.number_of_local_dofs()
        return tdim * ldof

    def cell_to_dof(self):
        return self.cell2dof

    def init_cell_to_dof(self):
        """
        构建局部自由度到全局自由度的映射矩阵

        Returns
        -------
        cell2dof : ndarray with shape (NC, ldof*tdim)
            NC: 单元个数
            ldof: p 次标量空间局部自由度的个数
            tdim: 对称张量的维数
        """
        mesh = self.mesh
        NN = mesh.number_of_nodes()
        NE = mesh.number_of_edges()
        NC = mesh.number_of_cells()

        gdim = self.geo_dimension()
        tdim = self.tensor_dimension()  # 张量维数
        p = self.p
        dof = self.dof  # 标量空间自由度管理对象

        c2d = dof.cell2dof[..., np.newaxis]
        ldof = dof.number_of_local_dofs()  # ldof : 标量空间单元上自由度个数
        cell2dof = np.zeros((NC, ldof, tdim),
                            dtype=np.int)  # 每个标量自由度变成 tdim 个自由度

        dofFlags = self.dof_flags_1()  # 把不同类型的自由度区分开来
        idx, = np.nonzero(dofFlags[0])  # 局部顶点自由度的编号
        cell2dof[:, idx, :] = tdim * c2d[:, idx] + np.arange(tdim)

        base0 = 0
        base1 = 0
        idx, = np.nonzero(dofFlags[1])  # 边内部自由度的编号
        if len(idx) > 0:
            base0 += NN  # 这是标量编号的新起点
            base1 += tdim * NN  # 这是张量自由度编号的新起点
            #  0号局部自由度对应的是切向不连续的自由度, 留到后面重新编号
            cell2dof[:, idx,
                     1:] = base1 + (tdim - 1) * (c2d[:, idx] -
                                                 base0) + np.arange(tdim - 1)

        idx, = np.nonzero(dofFlags[2])
        if len(idx) > 0:
            edof = p - 1
            base0 += edof * NE
            base1 += (tdim - 1) * edof * NE
            if gdim == 2:
                cell2dof[:, idx, :] = base1 + tdim * (c2d[:, idx] -
                                                      base0) + np.arange(tdim)
            elif gdim == 3:
                # 1, 2, 3 号局部自由度对应切向不连续的张量自由度, 留到后面重新编号
                # TODO: check it is right
                cell2dof[:, idx.reshape(-1, 1),
                         np.array([0, 4, 5])] = base1 + (tdim - 3) * (
                             c2d[:, idx] - base0) + np.arange(tdim - 3)

        fdof = (p + 1) * (p + 2) // 2 - 3 * p  # 边内部自由度
        if gdim == 3:
            idx, = np.nonzero(dofFlags[3])
            if len(idx) > 0:
                NF = mesh.number_of_faces()
                base0 += fdof * NF
                base1 += (tdim - 3) * fdof * NF
                cell2dof[:, idx, :] = base1 + tdim * (c2d[:, idx] -
                                                      base0) + np.arange(tdim)
            cdof = ldof - 4 * fdof - 6 * edof - 4  # 单元内部自由度
        else:
            cdof = fdof

        idx, = np.nonzero(dofFlags[1])
        if len(idx) > 0:
            base1 += tdim * cdof * NC
            cell2dof[:, idx, 0] = base1 + np.arange(NC * len(idx)).reshape(
                NC, len(idx))

        if gdim == 3:
            base1 += NC * len(idx)
            idx, = np.nonzero(dofFlags[2])
            print(idx)
            if len(idx) > 0:
                cell2dof[:, idx.reshape(-1, 1),
                         np.array([1, 2, 3])] = base1 + np.arange(
                             NC * len(idx) * 3).reshape(NC, len(idx), 3)

        self.cell2dof = cell2dof.reshape(NC, -1)

    def geo_dimension(self):
        return self.dim

    def tensor_dimension(self):
        dim = self.dim
        return dim * (dim - 1) // 2 + dim

    def interpolation_points(self):
        return self.dof.interpolation_points()

    def dof_flags(self):
        """ 对标量空间中的自由度进行分类, 分为边内部自由度, 面内部自由度(如果是三维空间的话)及其它自由度 

        Returns
        -------

        isOtherDof : ndarray, (ldof,)
            除了边内部和面内部自由度的其它自由度
        isEdgeDof : ndarray, (ldof, 3) or (ldof, 6) 
            每个边内部的自由度
        isFaceDof : ndarray, (ldof, 4)
            每个面内部的自由度
        -------

        """
        dim = self.geo_dimension()
        dof = self.dof

        isPointDof = dof.is_on_node_local_dof()
        isEdgeDof = dof.is_on_edge_local_dof()
        isEdgeDof[isPointDof] = False

        isEdgeDof0 = np.sum(isEdgeDof, axis=-1) > 0  #
        isOtherDof = (~isEdgeDof0)  # 除了边内部自由度之外的其它自由度
        # dim = 2: 包括点和面内部自由度
        # dim = 3: 包括点, 面内部和体内部自由度
        if dim == 2:
            return isOtherDof, isEdgeDof
        elif dim == 3:
            isFaceDof = dof.is_on_face_local_dof()
            isFaceDof[isPointDof, :] = False
            isFaceDof[isEdgeDof0, :] = False

            isFaceDof0 = np.sum(isFaceDof, axis=-1) > 0
            isOtherDof = isOtherDof & (~isFaceDof0)  # 三维情形下, 从其它自由度中除去面内部自由度

            return isOtherDof, isEdgeDof, isFaceDof
        else:
            raise ValueError('`dim` should be 2 or 3!')

    def dof_flags_1(self):
        """ 
        对标量空间中的自由度进行分类, 分为:
            点上的自由由度
            边内部的自由度
            面内部的自由度
            体内部的自由度

        Returns
        -------

        """
        gdim = self.geo_dimension()  # the geometry space dimension
        dof = self.dof
        isPointDof = dof.is_on_node_local_dof()
        isEdgeDof = dof.is_on_edge_local_dof()
        isEdgeDof[isPointDof] = False
        isEdgeDof0 = np.sum(isEdgeDof, axis=-1) > 0
        if gdim == 2:
            return isPointDof, isEdgeDof0, ~(isPointDof | isEdgeDof0)
        elif gdim == 3:
            isFaceDof = dof.is_on_face_local_dof()
            isFaceDof[isPointDof, :] = False
            isFaceDof[isEdgeDof0, :] = False

            isFaceDof0 = np.sum(isFaceDof, axis=-1) > 0
            return isPointDof, isEdgeDof0, isFaceDof0, ~(
                isPointDof | isEdgeDof0 | isFaceDof0)
        else:
            raise ValueError('`dim` should be 2 or 3!')

    def basis(self, bc, cellidx=None):
        """

        Parameters
        ----------
        bc : ndarray with shape (NQ, dim+1)
            bc[i, :] is i-th quad point
        cellidx : ndarray
            有时我我们只需要计算部分单元上的基函数
        Returns
        -------
        phi : ndarray with shape (NQ, NC, ldof*tdim, 3 or 6)
            NQ: 积分点个数
            NC: 单元个数
            ldof: 标量空间的单元自由度个数
            tdim: 对称张量的维数
        """
        mesh = self.mesh

        gdim = self.geo_dimension()
        tdim = self.tensor_dimension()

        if cellidx is None:
            NC = mesh.number_of_cells()
            cell2edge = mesh.ds.cell_to_edge()
        else:
            NC = len(cellidx)
            cell2edge = mesh.ds.cell_to_edge()[cellidx]

        phi0 = self.space.basis(bc)  # the shape of phi0 is (NQ, ldof)
        shape = list(phi0.shape)
        shape.insert(-1, NC)
        shape += [tdim, tdim]
        # The shape of `phi` is (NQ, NC, ldof, tdim, tdim), where
        #   NQ : the number of quadrature points
        #   NC : the number of cells
        #   ldof : the number of dofs in each cell
        #   tdim : the dimension of symmetric tensor matrix
        phi = np.zeros(shape, dtype=np.float)

        dofFlag = self.dof_flags()
        # the dof on the vertex and the interior of the cell
        isOtherDof = dofFlag[0]
        idx, = np.nonzero(isOtherDof)
        if len(idx) > 0:
            phi[..., idx[..., np.newaxis],
                range(tdim),
                range(tdim)] = phi0[..., np.newaxis, idx, np.newaxis]

        isEdgeDof = dofFlag[1]
        for i, isDof in enumerate(isEdgeDof.T):
            phi[..., isDof, :, :] = np.einsum('...j, imn->...ijmn',
                                              phi0[..., isDof],
                                              self.TE[cell2edge[:, i]])

        if gdim == 3:
            if cellidx is None:
                cell2face = mesh.ds.cell_to_face()
            else:
                cell2face = mesh.ds.cell_to_face()[cellidx]
            isFaceDof = dofFlag[2]
            for i, isDof in enumerate(isFaceDof.T):
                phi[..., isDof, :, :] = np.einsum('...j, imn->...ijmn',
                                                  phi0[..., isDof],
                                                  self.TF[cell2face[:, i]])
        # The shape of `phi` should be (NQ, NC, ldof*tdim, tdim)?
        shape = phi.shape[:-3] + (-1, tdim)
        return phi.reshape(shape)

    def div_basis(self, bc, cellidx=None):
        mesh = self.mesh

        gdim = self.geo_dimension()
        tdim = self.tensor_dimension()

        # the shape of `gphi` is (NQ, NC, ldof, gdim)
        gphi = self.space.grad_basis(bc, cellidx=cellidx)
        shape = list(gphi.shape)
        shape.insert(-1, tdim)
        # the shape of `dphi` is (NQ, NC, ldof, tdim, gdim)
        dphi = np.zeros(shape, dtype=np.float)

        dofFlag = self.dof_flags()
        # the dof on the vertex and the interior of the cell
        isOtherDof = dofFlag[0]
        dphi[..., isOtherDof, :, :] = np.einsum('...ijm, kmn->...ijkn',
                                                gphi[...,
                                                     isOtherDof, :], self.T)

        if cellidx is None:
            cell2edge = mesh.ds.cell_to_edge()
        else:
            cell2edge = mesh.ds.cell_to_edge()[cellidx]
        isEdgeDof = dofFlag[1]
        for i, isDof in enumerate(isEdgeDof.T):
            VAL = np.einsum('ijk, kmn->ijmn', self.TE[cell2edge[:, i]], self.T)
            dphi[..., isDof, :, :] = np.einsum('...ikm, ijmn->...ikjn',
                                               gphi[..., isDof, :], VAL)

        if gdim == 3:
            if cellidx is None:
                cell2face = mesh.ds.cell_to_face()
            else:
                cell2face = mesh.ds.cell_to_face()[cellidx]
            isFaceDof = dofFlag[2]
            for i, isDof in enumerate(isFaceDof.T):
                VAL = np.einsum('ijk, kmn->ijmn', self.TF[cell2face[:, i]],
                                self.T)
                dphi[..., isDof, :, :] = np.einsum('...ikm, ijmn->...ikjn',
                                                   gphi[..., isDof, :], VAL)

        # The new shape of `dphi` is `(NQ, NC, ldof*tdim, gdim)`, where
        shape = dphi.shape[:-3] + (-1, gdim)
        return dphi.reshape(shape)

    def value(self, uh, bc, cellidx=None):
        phi = self.basis(bc, cellidx=cellidx)
        cell2dof = self.cell_to_dof()
        tdim = self.tensor_dimension()
        if cellidx is None:
            uh = uh[cell2dof]
        else:
            uh = uh[cell2dof[cellidx]]
        phi = np.einsum('...jk, kmn->...jmn', phi, self.T)
        val = np.einsum('...ijmn, ij->...imn', phi, uh)
        return val

    def div_value(self, uh, bc, cellidx=None):
        dphi = self.div_basis(bc, cellidx=cellidx)
        cell2dof = self.cell_to_dof()
        tdim = self.tensor_dimension()
        if cellidx is None:
            uh = uh[cell2dof]
        else:
            uh = uh[cell2dof[cellidx]]
        val = np.einsum('...ijm, ij->...im', dphi, uh)
        return val

    def interpolation(self, u):

        mesh = self.mesh
        gdim = self.geo_dimension()
        tdim = self.tensor_dimension()

        if gdim == 2:
            idx = np.array([(0, 0), (1, 1), (0, 1)])
        elif gdim == 3:
            idx = np.array([(0, 0), (1, 1), (2, 2), (1, 2), (0, 2), (0, 1)])

        ipoint = self.dof.interpolation_points()
        c2d = self.dof.cell2dof
        val = u(ipoint)[c2d]

        ldof = self.dof.number_of_local_dofs()
        cell2dof = self.cell2dof.reshape(-1, ldof, tdim)

        uI = Function(self)
        dofFlag = self.dof_flags()
        isOtherDof = dofFlag[0]
        idx0, = np.nonzero(isOtherDof)
        uI[cell2dof[:, idx0, :]] = val[:, idx0][..., idx[:, 0], idx[:, 1]]

        isEdgeDof = dofFlag[1]
        cell2edge = self.mesh.ds.cell_to_edge()
        for i, isDof in enumerate(isEdgeDof.T):
            TE = np.einsum('ijk, kmn->ijmn', self.TE[cell2edge[:, i]], self.T)
            uI[cell2dof[:, isDof, :]] = np.einsum('ikmn, ijmn->ikj',
                                                  val[:, isDof, :, :], TE)

        if gdim == 3:
            cell2face = mesh.ds.cell_to_face()
            isFaceDof = dofFlag[2]
            for i, isDof in enumerate(isFaceDof.T):
                TF = np.einsum('ijk, kmn->ijmn', self.TF[cell2face[:, i]],
                               self.T)
                uI[cell2dof[:, isDof, :]] = np.einsum('ikmn, ijmn->ikj',
                                                      val[...,
                                                          isDof, :, :], TF)
        return uI

        def function(self, dim=None):
            f = Function(self)

        return f

    def array(self, dim=None):
        gdof = self.number_of_global_dofs()
        return np.zeros(gdof, dtype=np.float)
示例#5
0
from mpl_toolkits.mplot3d import Axes3D

from fealpy.mesh import MeshFactory as MF
from fealpy.mesh import TriangleMesh
from fealpy.mesh.core import multi_index_matrix2d
from fealpy.functionspace import LagrangeFiniteElementSpace

mesh = MF.one_triangle_mesh(meshtype='equ')

space = LagrangeFiniteElementSpace(mesh, p=5)

n = 50
bcs = multi_index_matrix2d(n) / n  # ldof = (n+1)(n+2)/2
ps = mesh.bc_to_point(bcs).reshape(-1, 2)

val = space.basis(bcs)  # (NQ, 1, ldof)

val = space.grad_basis(bcs)  # (NQ, NC, ldof, GD)

val = val[:, 0, 0]

fig = plt.figure()
axes = fig.gca()
mesh.add_plot(axes)
mesh.find_node(axes, node=ps, markersize=20)

fig = plt.figure()
axes = fig.add_subplot(projection='3d')
axes.plot_trisurf(ps[:, 0],
                  ps[:, 1],
                  val,
示例#6
0
NC = mesh.number_of_cells()
print("网格中节点、边和单元的个数分别为:", NN, NE, NC)

print('创建拉格朗日有限元空间...')
space = LagrangeFiniteElementSpace(mesh, p=p)
ldof = space.number_of_local_dofs()
gdof = space.number_of_global_dofs()

print('拉格朗日空间的次数为:', p)
print('每个单元上的局部自由度个数:', ldof)
print('每个单元上的全局自由度个数', gdof)

print('计算空间基函数在每个单元重心坐标点处的值...')
bc = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]], dtype=np.float64)  # (3, 3)
ps = mesh.bc_to_point(bc)  # (NQ, NC, 2)

phi = space.basis(bc)
gphi = space.grad_basis(bc)

print('重心坐标数组:', bc)
print('bc.shape:', bc.shape)
print('phi.shape:', phi.shape)
print('gphi.shape:', gphi.shape)

fig = plt.figure()
axes = fig.gca()
mesh.add_plot(axes)
mesh.find_node(axes, showindex=True)
mesh.find_cell(axes, showindex=True)
plt.show()