Exemple #1
0
class ParabolicFEMModel():
    def __init__(self, pde, mesh, p=1, q=6):
        from fealpy.functionspace import LagrangeFiniteElementSpace
        from fealpy.boundarycondition import BoundaryCondition
        self.space = LagrangeFiniteElementSpace(mesh, p)
        self.mesh = self.space.mesh
        self.pde = pde

        self.ftype = self.mesh.ftype
        self.itype = self.mesh.itype

        self.M = self.space.mass_matrix()
        self.A = self.space.stiff_matrix()

    def init_solution(self, timeline):
        NL = timeline.number_of_time_levels()
        gdof = self.space.number_of_global_dofs()
        uh = np.zeros((gdof, NL), dtype=self.mesh.ftype)
        uh[:,
           0] = self.space.interpolation(lambda x: self.pde.solution(x, 0.0))
        return uh

    def interpolation(self, u, timeline):
        NL = timeline.number_of_time_levels()
        gdof = self.space.number_of_global_dofs()
        ps = self.space.interpolation_points()
        uI = np.zeros((gdof, NL), dtype=self.mesh.ftype)
        times = timeline.all_time_levels()
        for i, t in enumerate(times):
            uI[..., i] = u(ps, t)
        return uI

    def get_current_left_matrix(self, timeline):
        dt = timeline.current_time_step_length()
        return self.M + 0.5 * dt * self.A

    def get_current_right_vector(self, uh, timeline):
        i = timeline.current
        dt = timeline.current_time_step_length()
        t0 = timeline.current_time_level()
        t1 = timeline.next_time_level()
        f = lambda x: self.pde.source(x, t0) + self.pde.source(x, t1)
        F = self.space.source_vector(f)
        return self.M @ uh[:, i] - 0.5 * dt * self.A @ uh[:, i]

    def apply_boundary_condition(self, A, b, timeline):
        t1 = timeline.next_time_level()
        bc = BoundaryCondition(self.space,
                               neuamn=lambda x: self.pde.neuman(x, t1))
        b = bc.apply_neuman_bc(b)
        return A, b

    def solve(self, uh, A, b, solver, timeline):
        i = timeline.current
        uh[:, i + 1] = solver(A, b)
Exemple #2
0
def f(n):
    # 准备网格
    node = np.array([0, 1], dtype=np.float)
    cell = np.array([[0, 1]], dtype=np.int)
    mesh = IntervalMesh(node, cell)
    mesh.uniform_refine(n=n)
    node = mesh.entity('node')
    cell = mesh.entity('cell')
    #print(node)
    #print(cell)
    # 准备空间
    space = LagrangeFiniteElementSpace(mesh, p=p)
    #ipoints = space.interpolation_points()
    #uI = u(ipoints)

    uI = space.interpolation(u)

    error1 = space.integralalg.L2_error(u, uI)
    error2 = space.integralalg.L2_error(du, uI.grad_value)

    return error1, error2
import numpy as np

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

from fealpy.pde.navier_stokes_equation_2d import SinCosData
from fealpy.mesh import MeshFactory
from fealpy.functionspace import LagrangeFiniteElementSpace

pde = SinCosData()
mesh = MeshFactory.boxmesh2d(pde.box, nx=10, ny=10, meshtype='tri')

uspace = LagrangeFiniteElementSpace(mesh, p=2)
pspace = LagrangeFiniteElementSpace(mesh, p=1)

pI = pspace.interpolation(pde.pressure)
uI = uspace.interpolation(pde.velocity)

#  [[phi, 0], [0, phi]]
#  [[phi_x, phi_y], [0, 0]] [[0, 0], [phi_x, phi_y]]

A = uspace.stiff_matrix()
B = uspace.div_matrix(pspace)

fig = plt.figure()
axes = fig.gca()
bc = np.array([1 / 3] * 3)
point = mesh.bc_to_point(bc)
p = pI.value(bc)
u = uI.value(bc)
mesh.add_plot(axes, cellcolor=p)
Exemple #4
0
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

from fealpy.pde.poisson_2d import CosCosData as PDE
from fealpy.functionspace import LagrangeFiniteElementSpace

pde = PDE()

mesh = pde.init_mesh(n=4, meshtype='tri')

space = LagrangeFiniteElementSpace(mesh, 2)

uI = space.interpolation(pde.solution)  # 有限元空间的函数,同地它也是一个数组

bc = np.array([1 / 3, 1 / 3, 1 / 3], dtype=np.float64)
val = uI(bc)  # (NC, )
val = uI.value(bc)  # (NC, )
gval = uI.grad_value(bc)  #(NC, GD)

L2error = space.integralalg.error(pde.solution, uI, q=5, power=2)
H1error = space.integralalg.error(pde.gradient, uI.grad_value, q=5, power=2)
print(H1error)

fig = plt.figure()
axes = fig.add_subplot(projection='3d')
uI.add_plot(axes, cmap='rainbow')
plt.show()
Exemple #5
0
        shape = len(val.shape)*(1, )
        kappa = np.array([1,0], dtype=np.float64).reshape(shape)
        val += self.solution(p)
        return val, kappa



pde = MyPde()

# print(pde.solution.coordtype)
mf = MeshFactory()
box = [0,1,0,1]
mesh = mf.boxmesh2d(box, nx=40, ny=40, meshtype='tri')
space = LagrangeFiniteElementSpace(mesh,p=1)
#space提供一个插值函数  uI
uI = space.interpolation(pde.solution)#空间中的有限元函数,也是一个数组
# print('uI[0:10]:',uI[0:10])#打印前面10个自由度的值
bc = np.array([1/3,1/3,1/3],dtype=mesh.ftype)
val = uI(bc)#(1, NC)有限元函数在每个单元的重心处的函数值
# print('val[0:10]:',val[1:10])

val0 = uI(bc)#(NC,)
val1 = uI.grad_value(bc)#(NC,2)
# print('val0[0:10]:',val0[1:10])
# print('val1[0:10]:',val1[1:10])

#插值误差
error0 = space.integralalg.L2_error(pde.solution, uI)
error1 = space.integralalg.L2_error(pde.gradient, uI.grad_value)
# print('L2:',error0,'H1:',error1)
#
Exemple #6
0
    def test_interpolation_plane(self):
        def u(p):
            x = p[..., 0]
            y = p[..., 1]
            return x * y

        node = np.array([(0, 0), (1, 0), (1, 1), (0, 1)], dtype=np.float)
        cell = np.array([(1, 2, 0), (3, 0, 2)], dtype=np.int)
        mesh = TriangleMesh(node, cell)

        node = mesh.entity('node')
        cell = mesh.entity('cell')
        tritree = Tritree(node, cell)
        mesh = tritree.to_conformmesh()

        space = LagrangeFiniteElementSpace(mesh, p=2)
        uI = space.interpolation(u)
        error0 = space.integralalg.L2_error(u, uI)

        fig = plt.figure()
        axes = fig.gca()
        mesh.add_plot(axes)
        mesh.find_node(axes, node=space.interpolation_points(), showindex=True)

        data = tritree.interpolation(uI)
        options = tritree.adaptive_options(method='numrefine',
                                           data={"q": data},
                                           maxrefine=1,
                                           p=2)
        if 1:
            #eta = space.integralalg.integral(lambda x : uI.grad_value(x)**2, celltype=True, barycenter=True)
            #eta = eta.sum(axis=-1)
            eta = np.array([1, 0], dtype=np.int)
            tritree.adaptive(eta, options)
        else:
            tritree.uniform_refine(options=options)

        fig = plt.figure()
        axes = fig.gca()
        tritree.add_plot(axes)
        tritree.find_node(axes, showindex=True)

        mesh = tritree.to_conformmesh(options)
        space = LagrangeFiniteElementSpace(mesh, p=2)
        data = options['data']['q']
        uh = space.to_function(data)

        error1 = space.integralalg.L2_error(u, uh)

        data = tritree.interpolation(uh)
        isLeafCell = tritree.is_leaf_cell()

        fig = plt.figure()
        axes = fig.gca()
        tritree.add_plot(axes)
        tritree.find_node(axes,
                          node=space.interpolation_points(),
                          showindex=True)
        tritree.find_cell(axes, index=isLeafCell, showindex=True)

        options = tritree.adaptive_options(method='numrefine',
                                           data={"q": data},
                                           maxrefine=1,
                                           maxcoarsen=1,
                                           p=2)
        if 1:
            #eta = space.integralalg.integral(lambda x : uI.grad_value(x)**2, celltype=True, barycenter=True)
            #eta = eta.sum(axis=-1)
            eta = np.array([-1, -1, -1, -1, 0, 1], dtype=np.int)
            tritree.adaptive(eta, options)
        else:
            tritree.uniform_refine(options=options)

        mesh = tritree.to_conformmesh(options)
        space = LagrangeFiniteElementSpace(mesh, p=2)
        data = options['data']['q']
        uh = space.to_function(data)

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

        error2 = space.integralalg.L2_error(u, uh)
        print(error0)
        print(error1)
        print(error2)
        plt.show()
from scipy.sparse import coo_matrix, csr_matrix, csc_matrix, spdiags, bmat

from fealpy.pde.linear_elasticity_model import PolyModel3d as PDE
from fealpy.functionspace import LagrangeFiniteElementSpace
from fealpy.boundarycondition import DirichletBC
from fealpy.solver.LinearElasticityRLFEMFastSolver import LinearElasticityRLFEMFastSolver as FastSovler

n = int(sys.argv[1])

pde = PDE(lam=10000.0, mu=1.0)
mu = pde.mu
lam = pde.lam
mesh = pde.init_mesh(n=n)

space = LagrangeFiniteElementSpace(mesh, p=1, q=1)
M, G = space.recovery_linear_elasticity_matrix(lam, mu, format=None)
F = space.source_vector(pde.source, dim=3)

uh = space.function(dim=3)
isBdDof = space.set_dirichlet_bc(uh, pde.dirichlet)

solver = FastSovler(lam, mu, M, G, isBdDof)

solver.solve(uh, F, tol=1e-12)

uI = space.interpolation(pde.displacement, dim=3)

e = uh - uI
error = np.sqrt(np.mean(e**2))
print(error)
Exemple #8
0
#     err = np.sqrt(np.sum(eta ** 2))
#     if err < tol:
#         break
#     isMarkedCell = smesh.refine_marker(eta, rtheta, method='L2')
#
#     # |--- test
#     # isMarkedCell[smesh.ds.cellstart:] = True
#
#     smesh.refine_triangle_rg(isMarkedCell)
#     i += 1
#     smesh.add_plot(plt)
#     plt.savefig('./test-' + str(i + 1) + '.png')
#     plt.close()

space = LagrangeFiniteElementSpace(smesh, p=1)
uh0 = space.interpolation(pde.init_value)

for j in range(0, nt):

    # 下一个的时间层 t1
    t1 = tmesh.next_time_level()
    print("t1=", t1)

    while True:
        # 下一层时间步的有限元解
        uh1 = space.function()
        A = c * space.stiff_matrix()  # 刚度矩阵
        M = space.mass_matrix()  # 质量矩阵
        dt = tmesh.current_time_step_length()  # 时间步长
        G = M + dt * A  # 隐式迭代矩阵
Exemple #9
0
class CahnHilliardRFEMModel():
    def __init__(self, pde, n, tau, q):
        self.pde = pde
        self.mesh = pde.space_mesh(n)
        self.timemesh, self.tau = self.pde.time_mesh(tau)
        self.femspace = LagrangeFiniteElementSpace(self.mesh, 1)

        self.uh0 = self.femspace.interpolation(pde.initdata)
        self.uh1 = self.femspace.function()

        self.area = self.mesh.entity_measure('cell')

        self.integrator = self.mesh.integrator(q)
        self.integralalg = IntegralAlg(self.integrator, self.mesh, self.area)

        self.A, self.B, self.gradphi = grad_recovery_matrix(self.femspace)
        self.M = doperator.mass_matrix(self.femspace, self.integrator,
                                       self.area)
        self.K = self.get_stiff_matrix()
        self.D = self.M + self.tau * self.K
        self.ml = pyamg.ruge_stuben_solver(self.D)
        print(self.ml)
        self.current = 0

    def get_stiff_matrix(self):
        mesh = self.mesh
        area = self.area

        gradphi = self.gradphi
        A = self.A
        B = self.B
        NC = mesh.number_of_cells()
        NN = mesh.number_of_nodes()

        node = mesh.entity('node')
        edge = mesh.entity('edge')
        cell = mesh.entity('cell')

        edge2cell = mesh.ds.edge_to_cell()
        isBdEdge = (edge2cell[:, 0] == edge2cell[:, 1])
        bdEdge = edge[isBdEdge]
        cellIdx = edge2cell[isBdEdge, [0]]

        # construct the unit outward normal on the boundary
        W = np.array([[0, -1], [1, 0]], dtype=np.int)
        n = (node[bdEdge[:, 1], ] - node[bdEdge[:, 0], :]) @ W
        h = np.sqrt(np.sum(n**2, axis=1))
        n /= h.reshape(-1, 1)

        # 计算梯度的恢复矩阵
        I = np.einsum('ij, k->ijk', cell, np.ones(3))
        J = I.swapaxes(-1, -2)

        val = np.einsum('i, ij, ik->ijk', area, gradphi[:, :, 0], gradphi[:, :,
                                                                          0])
        P = csc_matrix((val.flat, (I.flat, J.flat)), shape=(NN, NN))

        val = np.einsum('i, ij, ik->ijk', area, gradphi[:, :, 0], gradphi[:, :,
                                                                          1])
        Q = csc_matrix((val.flat, (I.flat, J.flat)), shape=(NN, NN))

        val = np.einsum('i, ij, ik->ijk', area, gradphi[:, :, 1], gradphi[:, :,
                                                                          1])
        S = csc_matrix((val.flat, (I.flat, J.flat)), shape=(NN, NN))

        K = A.transpose() @ P @ A + A.transpose() @ Q @ B + B.transpose(
        ) @ Q.transpose() @ A + B.transpose() @ S @ B

        # 中间的边界上的两项
        I = np.einsum('ij, k->ijk', bdEdge, np.ones(3))
        J = np.einsum('ij, k->ikj', cell[cellIdx], np.ones(2))
        val0 = 0.5 * h.reshape(-1, 1) * n[:, [0]] * gradphi[cellIdx, :, 0]
        val0 = np.repeat(val0, 2, axis=0).reshape(-1, 2, 2)
        P0 = csc_matrix((val0.flat, (I.flat, J.flat)), shape=(NN, NN))

        val0 = 0.5 * h.reshape(-1, 1) * n[:, [0]] * gradphi[cellIdx, :, 1]
        val0 = np.repeat(val0, 2, axis=0).reshape(-1, 2, 2)
        Q0 = csc_matrix((val0.flat, (I.flat, J.flat)), shape=(NN, NN))

        val0 = 0.5 * h.reshape(-1, 1) * n[:, [1]] * gradphi[cellIdx, :, 0]
        val0 = np.repeat(val0, 2, axis=0).reshape(-1, 2, 2)
        P1 = csc_matrix((val0.flat, (I.flat, J.flat)), shape=(NN, NN))

        val0 = 0.5 * h.reshape(-1, 1) * n[:, [1]] * gradphi[cellIdx, :, 1]
        val0 = np.repeat(val0, 2, axis=0).reshape(-1, 2, 2)
        Q1 = csc_matrix((val0.flat, (I.flat, J.flat)), shape=(NN, NN))

        M = A.transpose() @ P0 @ A + A.transpose() @ Q0 @ B + B.transpose(
        ) @ P1 @ A + B.transpose() @ Q1 @ B

        K -= (M + M.transpose())
        K *= self.pde.epsilon**2

        # 边界上两个方向导数相乘的积分
        I = np.einsum('ij, k->ijk', bdEdge, np.ones(2))
        J = I.swapaxes(-1, -2)
        val = np.array([(1 / 3, 1 / 6), (1 / 6, 1 / 3)])
        val0 = np.einsum('i, jk->ijk', n[:, 0] * n[:, 0] / h, val)
        P = csc_matrix((val0.flat, (I.flat, J.flat)), shape=(NN, NN))
        val0 = np.einsum('i, jk->ijk', n[:, 0] * n[:, 1] / h, val)
        Q = csc_matrix((val0.flat, (I.flat, J.flat)), shape=(NN, NN))
        val0 = np.einsum('i, jk->ijk', n[:, 1] * n[:, 1] / h, val)
        S = csc_matrix((val0.flat, (I.flat, J.flat)), shape=(NN, NN))

        K += self.pde.epsilon**2 * (
            A.transpose() @ P @ A + A.transpose() @ Q @ B +
            B.transpose() @ Q @ A + B.transpose() @ S @ B)
        return K

        # def get_right_vector(self):

    #    uh = self.uh0
    #    b =  self.get_non_linear_vector()
    #    return self.M@uh  - self.tau*b

    # def get_non_linear_vector(self):
    #    uh = self.uh0
    #    bcs, ws = self.integrator.quadpts, self.integrator.weights
    #    gradphi = self.femspace.grad_basis(bcs)

    #    uval = uh.value(bcs)
    #    guval = uh.grad_value(bcs)
    #    fval = (3*uval[..., np.newaxis]**2 - 1)*guval
    #    bb = np.einsum('i, ikm, ikjm, k->kj', ws, fval, gradphi, self.area)
    #    cell2dof = self.femspace.cell_to_dof()
    #    gdof = self.femspace.number_of_global_dofs()
    #    b = np.bincount(cell2dof.flat, weights=bb.flat, minlength=gdof)
    #    return b

    def get_right_vector(self, t):
        uh = self.uh0

        def f(x):
            return self.pde.source(x, t)

        b = doperator.source_vector(f, self.femspace, self.integrator,
                                    self.area)
        return self.M @ uh + self.tau * b

    def solve(self):
        timemesh = self.timemesh
        tau = self.tau
        N = len(timemesh)
        print(N)
        D = self.D
        for i in range(N):
            t = timemesh[i]
            b = self.get_right_vector(t)
            # self.uh1[:] =  spsolve(D, b)
            self.uh1[:] = self.ml.solve(b, tol=1e-12, accel='cg').reshape(
                (-1, ))

            self.current = i
            if self.current % 2 == 0:
                self.show_soultion()
            self.uh0[:] = self.uh1[:]
        error = self.get_L2_error((N - 1) * tau)
        print(error)

    #    def step(self):
    #        D = self.D
    #        b = self.get_right_vector(self.current)
    #        self.uh[:, self.current + 1] = spsolve(D, b)
    #        self.current += 1

    def show_soultion(self):
        mesh = self.mesh
        timemesh = self.timemesh
        cell = mesh.entity('cell')
        node = mesh.entity('node')
        fig = plt.figure()
        fig.set_facecolor('white')
        axes = fig.gca(projection='3d')
        axes.plot_trisurf(node[:, 0],
                          node[:, 1],
                          cell,
                          self.uh0,
                          cmap=plt.cm.jet,
                          lw=0.0)
        plt.savefig('./results/cahnHilliard' + str(self.current) + '.png')

    def get_L2_error(self, t):
        def solution(x):
            return self.pde.solution(x, t)

        u = solution
        uh = self.uh0.value
        L2 = self.integralalg.L2_error(u, uh)
        return L2
maxit = int(sys.argv[2])

pde = CosCosData()
mesh = pde.init_mesh(n=4)

errorType = [
    '$|| u - u_h||_{\Omega,0}$', '$||\\nabla u - \\nabla u_h||_{\Omega, 0}$'
]
errorMatrix = np.zeros((2, maxit), dtype=np.float)
NDof = np.zeros(maxit, dtype=np.float)

for i in range(maxit):
    space = LagrangeFiniteElementSpace(mesh, p=p)
    NDof[i] = space.number_of_global_dofs()

    uI = space.interpolation(pde.solution)
    uh = space.function()
    A = space.stiff_matrix()
    F = space.source_vector(pde.source)

    bc = RobinBC(space, pde.robin)
    bc.apply(A, F)  # Here is the case for pure Robin bc
    uh[:] = spsolve(A, F)  # we add a addtional dof

    errorMatrix[0, i] = space.integralalg.L2_error(pde.solution, uh)
    errorMatrix[1, i] = space.integralalg.L2_error(pde.gradient, uh.grad_value)

    if i < maxit - 1:
        mesh.uniform_refine()

fig = plt.figure()
Exemple #11
0
class PoissonFEMModel(object):
    def __init__(self, pde, mesh, p, q=3):
        self.space = LagrangeFiniteElementSpace(mesh, p, q=q)
        self.mesh = self.space.mesh
        self.pde = pde
        self.uh = self.space.function()
        self.uI = self.space.interpolation(pde.solution)
        self.integrator = self.mesh.integrator(p + 2)

    def recover_estimate(self, rguh):
        qf = self.integrator
        bcs, ws = qf.quadpts, qf.weights

        val0 = rguh.value(bcs)
        val1 = self.uh.grad_value(bcs)
        l = np.sum((val1 - val0)**2, axis=-1)
        e = np.einsum('i, ij->j', ws, l)
        e *= self.space.cellmeasure
        return np.sqrt(e)

    def residual_estimate(self, uh=None):
        if uh is None:
            uh = self.uh
        mesh = self.mesh
        GD = mesh.geo_dimension()
        NC = mesh.number_of_cells()

        n = mesh.face_normal()
        bc = np.array([1 / (GD + 1)] * (GD + 1), dtype=mesh.ftype)
        grad = uh.grad_value(bc)

        ps = mesh.bc_to_point(bc)
        try:
            d = self.pde.diffusion_coefficient(ps)
        except AttributeError:
            d = np.ones(NC, dtype=mesh.ftype)

        if isinstance(d, float):
            grad *= d
        elif len(d) == GD:
            grad = np.einsum('m, im->im', d, grad)
        elif isinstance(d, np.ndarray):
            if len(d.shape) == 1:
                grad = np.einsum('i, im->im', d, grad)
            elif len(d.shape) == 2:
                grad = np.einsum('im, im->im', d, grad)
            elif len(d.shape) == 3:
                grad = np.einsum('imn, in->in', d, grad)

        if GD == 2:
            face2cell = mesh.ds.edge_to_cell()
            h = np.sqrt(np.sum(n**2, axis=-1))
        elif GD == 3:
            face2cell = mesh.ds.face_to_cell()
            h = np.sum(n**2, axis=-1)**(1 / 4)

        J = h * np.sum(
            (grad[face2cell[:, 0]] - grad[face2cell[:, 1]]) * n, axis=-1)**2

        NC = mesh.number_of_cells()
        eta = np.zeros(NC, dtype=mesh.ftype)
        np.add.at(eta, face2cell[:, 0], J)
        np.add.at(eta, face2cell[:, 1], J)
        return np.sqrt(eta)

    def get_left_matrix(self):
        return self.space.stiff_matrix()

    def get_right_vector(self):
        return self.space.source_vector(self.pde.source)

    def solve(self):
        bc = DirichletBC(self.space, self.pde.dirichlet)

        start = timer()
        A = self.get_left_matrix()
        b = self.get_right_vector()
        end = timer()
        self.A = A

        print("Construct linear system time:", end - start)

        AD, b = bc.apply(A, b)

        start = timer()
        self.uh[:] = spsolve(AD, b)
        end = timer()
        print("Solve time:", end - start)

        ls = {'A': AD, 'b': b, 'solution': self.uh.copy()}

        return ls  # return the linear system

    def l2_error(self):
        e = self.uh - self.uI
        return np.sqrt(np.mean(e**2))

    def uIuh_error(self):
        e = self.uh - self.uI
        return np.sqrt(e @ self.A @ e)

    def L2_error(self, uh=None):
        u = self.pde.solution
        if uh is None:
            uh = self.uh.value
        else:
            uh = uh.value
        L2 = self.space.integralalg.L2_error(u, uh)
        return L2

    def H1_semi_error(self, uh=None):
        gu = self.pde.gradient
        if uh is None:
            guh = self.uh.grad_value
        else:
            guh = uh.grad_value
        H1 = self.space.integralalg.L2_error(gu, guh)
        return H1

    def recover_error(self, rguh):
        gu = self.pde.gradient
        guh = rguh.value
        mesh = self.mesh
        re = self.space.integralalg.L2_error(gu, guh, mesh)
        return re
Exemple #12
0
fig0 = plt.figure()
axes = fig0.gca()
mesh.add_plot(axes)

fig1 = plt.figure()
axes = fig1.gca(projection='3d')
uI.add_plot(axes, cmap='rainbow')
plt.show()

if False:
    box = [0, 1, 0, 1]
    mesh = mf.boxmesh2d(box, nx=n, ny=n, meshtype='tri')
    space = LagrangeFiniteElementSpace(mesh, p=p)

    # 插值
    uI = space.interpolation(pde.solution)  # 是个有限元函数,同时也是一个数组

    print('uI[0:10]:', uI[0:10])  # 打印前面 10 个自由度的值

    bc = np.array([1 / 3, 1 / 3, 1 / 3], dtype=mesh.ftype)  # (3, )
    val0 = uI(bc)  # (NC, )
    val1 = uI.grad_value(bc)  # (NC, 2)

    print('val0[0:10]:', val0[1:10])  # 打 uI 在前面 10 个单元重心处的函数值
    print('val1[0:10]:', val1[1:10])  # 打 uI 在前面 10 个单元重心处的梯度值

    # 插值误差

    error0 = space.integralalg.L2_error(pde.solution, uI)
    error1 = space.integralalg.L2_error(pde.gradient, uI.grad_value)
    print('L2:', error0, 'H1:', error1)