def get_current_linear_system(self):
        V = self.V
        model = self.model

        t = self.currentTime

        S = self.stiffMatrix
        M = self.massMatrix
        k = model.diffusion_coefficient()
        bc = DirichletBC(self.V, lambda p: model.dirichlet(p, t), model.is_dirichlet_boundary)
        F = SourceForm(V, lambda p: model.source(p, t), 3).get_vector() 
        dt = self.dt
        if self.method is 'FM':
            b = dt*(F - k*[email protected][-1]) + [email protected][-1]
            A, b = bc.apply(M, b) 
            return A, b
        if self.method is 'BM':
            b = dt*F + [email protected][-1]
            A = M + dt*k*S
            A, b = bc.apply(A, b)
            return A, b
        if self.method is 'CN':
            b = dt*F + (M - 0.5*dt*k*S)@self.solution[-1]
            A = M + 0.5*dt*k*S
            A, b = bc.apply(A, b)
            return A, b
Exemple #2
0
def test_poisson_fem_2d():
    degree = 1  
    dim = 2
    nrefine = 4 
    maxit = 4 

    from fealpy.pde.poisson_2d import CosCosData as PDE

    pde = PDE()
    mesh = pde.init_mesh(n=nrefine)

    errorMatrix = np.zeros((2, maxit), dtype=np.float64)
    NDof = np.zeros(maxit, dtype=np.int64)

    for i in range(maxit):
        space = LagrangeFiniteElementSpace(mesh, p=degree)
        NDof[i] = space.number_of_global_dofs()
        bc = DirichletBC(space, pde.dirichlet) 

        uh = space.function()
        A = space.stiff_matrix()

        F = space.source_vector(pde.source)

        A, F = bc.apply(A, F, uh)

        uh[:] = spsolve(A, F).reshape(-1)

        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()
Exemple #3
0
    def solve_poisson_3d(self, n=2):
        from fealpy.pde.poisson_3d import CosCosCosData as PDE
        from fealpy.mesh import MeshFactory
        from fealpy.functionspace import LagrangeFiniteElementSpace
        from fealpy.boundarycondition import DirichletBC

        pde = PDE()
        mf = MeshFactory()
        m = 2**n
        box = [0, 1, 0, 1, 0, 1]
        mesh = mf.boxmesh3d(box, nx=m, ny=m, nz=m, meshtype='tet')
        space = LagrangeFiniteElementSpace(mesh, p=1)
        gdof = space.number_of_global_dofs()
        NC = mesh.number_of_cells()
        print('gdof:', gdof, 'NC:', NC)
        bc = DirichletBC(space, pde.dirichlet)
        uh = space.function()
        A = space.stiff_matrix()
        A = space.parallel_stiff_matrix(q=1)

        M = space.parallel_mass_matrix(q=2)
        M = space.mass_matrix()

        F = space.source_vector(pde.source)

        A, F = bc.apply(A, F, uh)

        solver = PETScSolver()
        solver.solve(A, F, uh)
        error = space.integralalg.L2_error(pde.solution, uh)
        print(error)
Exemple #4
0
    def solve_poisson_3d(self, n=5):
        from fealpy.pde.poisson_3d import CosCosCosData as PDE
        from fealpy.functionspace import LagrangeFiniteElementSpace
        from fealpy.boundarycondition import DirichletBC

        pde = PDE()
        mesh = pde.init_mesh(n=n)
        space = LagrangeFiniteElementSpace(mesh, p=1)
        bc = DirichletBC(space, pde.dirichlet)
        uh = space.function()
        A = space.stiff_matrix()
        F = space.source_vector(pde.source)

        A, F = bc.apply(A, F, uh)

        solver = PETScSolver()
        solver.solve(A, F, uh)
        error = space.integralalg.L2_error(pde.solution, uh)
        print(error)
def vem_solve(model, quadtree):
    mesh = quadtree.to_polygonmesh()
    V = VirtualElementSpace2d(mesh, 1)
    uh = FiniteElementFunction(V)
    vem = PoissonVEMModel(model, V)
    BC = DirichletBC(V, model.dirichlet)
    A, b = solve(vem, uh, dirichlet=BC, solver='direct')
    uI = V.interpolation(model.solution)
    eta = vem.recover_estimate(uh)
    uIuh = np.sqrt((uh - uI) @ A @ (uh - uI))
    return uh, V.number_of_global_dofs(), eta, uIuh
Exemple #6
0
def test_poisson():

    p = 1  # 有限元空间次数, 可以增大 p, 看输出结果的变化
    n = 4  # 初始网格加密次数
    maxit = 4  # 最大迭代次数

    pde = PDE()
    mesh = pde.init_mesh(n=n)

    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()  # 有限元空间自由度的个数
        bc = DirichletBC(space, pde.dirichlet)  # DirichletBC 条件

        uh = space.function()  # 有限元函数
        A = space.stiff_matrix()  # 刚度矩阵
        F = space.source_vector(pde.source)  # 载荷向量

        A, F = bc.apply(A, F, uh)  # 处理边界条件

        uh[:] = spsolve(A, F).reshape(-1)  # 稀疏矩阵直接解法器

        # ml = pyamg.ruge_stuben_solver(A)  # 代数多重网格解法器
        # uh[:] = ml.solve(F, tol=1e-12, accel='cg').reshape(-1)

        errorMatrix[0, i] = space.integralalg.L2_error(
            pde.solution, uh
        )  # 计算 L2 误差
        errorMatrix[1, i] = space.integralalg.L2_error(
            pde.gradient, uh.grad_value
        )  # 计算 H1 误差

        if i < maxit - 1:
            mesh.uniform_refine()  # 一致加密网格

    assert (errorMatrix < 1.0).all()
Exemple #7
0
    def Arctan(self, p=1, n=3):
        pde = ArctanData()

        node = np.array([[-1, -1], [1, -1], [1, 1], [-1, 1]], dtype=np.float_)
        cell = np.array([[0, 1, 2], [0, 2, 3]], dtype=np.int_)
        mesh = TriangleMesh(node, cell)
        mesh.uniform_refine(n=n)

        space = LagrangeFiniteElementSpace(mesh, p=p)
        uh = space.function()

        A = space.stiff_matrix()
        b = space.source_vector(pde.source)

        bc = DirichletBC(space, pde.dirichlet)
        A, b = bc.apply(A, b, uh)
        uh[:] = spsolve(A, b).reshape(-1)

        error0 = space.integralalg.L2_error(pde.solution, uh)
        error1 = space.integralalg.L2_error(pde.gradient, uh.grad_value)
        print(error0)
        print(error1)
Exemple #8
0
    def __init__(self, model, mesh, interval, N):
        super(HeatEquationSolver, self).__init__(interval)
        self.model = model
        self.dt = (interval[1] - interval[0])/N

        V = function_space(mesh, 'Lagrange', 1)
        uh = FiniteElementFunction(V)
        uh[:] = model.init_value(V.interpolation_points())

        self.solution = [uh]

        self.BC = DirichletBC(V, model.dirichlet, model.is_dirichlet_boundary)
        self.stiff_matrix = LaplaceSymetricForm(V, 3).get_matrix()
        self.mass_matrix = MassForm(V, 3).get_matrix()
 def apply_boundary_condition(self, A, b, timeline, sdc=False):
     if sdc is False:
         t1 = timeline.next_time_level()
         bc = DirichletBC(self.space, lambda x:self.pde.solution(x, t1), self.is_boundary_dof)
         A, b = bc.apply(A, b)
         return A, b
     else:
         bc = DirichletBC(self.space, lambda x:0, self.is_boundary_dof)
         A, b = bc.apply(A, b)
         return A, b
Exemple #10
0
box = [0, 1, 0, 1]

model = CosCosData()
mesh = rectangledomainmesh(box, nx=n, ny=n, meshtype='tri') 
maxit = 4 
Ndof = np.zeros(maxit, dtype=np.int)
error = np.zeros(maxit, dtype=np.float)
ratio = np.zeros(maxit, dtype=np.float)
for i in range(maxit):
    V = function_space(mesh, 'Lagrange', degree)
    uh = FiniteElementFunction(V)
    Ndof[i] = V.number_of_global_dofs() 
    a  = LaplaceSymetricForm(V, qt)
    L = SourceForm(V, model.source, qt)
    bc = DirichletBC(V, model.dirichlet, model.is_boundary)
    point = V.interpolation_points()
    solve(a, L, uh, dirichlet=bc, solver='direct')
    error[i] = L2_error(model.solution, uh, order=qt) 
    # error[i] = np.sqrt(np.sum((uh - model.solution(point))**2)/Ndof[i])
    if i < maxit-1:
        mesh.uniform_refine()

# 输出结果
ratio[1:] = error[0:-1]/error[1:]
print('Ndof:', Ndof)
print('error:', error)
print('ratio:', ratio)

#fig = plt.figure()
#axes = fig.gca()
Exemple #11
0
pde = BeamData2d(E=2 * 10**6, nu=0.3)
mu = pde.mu
lam = pde.lam
mesh = pde.init_mesh(n=n)

space = LagrangeFiniteElementSpace(mesh, p=p, q=4)
uh = space.function(dim=2)

A = space.linear_elasticity_matrix(lam, mu)
#A = space.recovery_linear_elasticity_matrix(lam, mu)
F = space.source_vector(pde.source, dim=2)

bc = NeumannBC(space, pde.neumann, threshold=pde.is_neumann_boundary)
F = bc.apply(F)

bc = DirichletBC(space, pde.dirichlet, threshold=pde.is_dirichlet_boundary)
A, F = bc.apply(A, F, uh)

ctx = DMumpsContext()
ctx.set_silent()
if ctx.myid == 0:
    ctx.set_centralized_sparse(A)
    x = F.copy()
    ctx.set_rhs(x)  # Modified in place
    ctx.run(job=6)  # Analysis + Factorization + Solve
    ctx.destroy()  # Cleanup

uh.T.flat[:] = x
# uh.T.flat[:] = spsolve(A, F) # (2, gdof ).flat

uI = space.interpolation(pde.displacement, dim=2)
Exemple #12
0
    def f(p):
        x = p[..., 0]
        y = p[..., 1]
        pi = np.pi
        return 2 * pi**2 * np.sin(pi * x) * np.sin(
            pi * y) + 12 * pi**2 * np.cos(pi * x) * np.cos(pi * y) + (
                -pi) * np.sin(pi * x) * np.cos(pi * y) - pi * np.cos(
                    pi * x) * np.sin(pi * y) + (1 + x**2 + y**2) * np.cos(
                        pi * x) * np.cos(pi * y)

    F = space.source_vector(f)
    A += B + M

    # 画出误差阶

    bc = DirichletBC(space, pde.dirichlet, threshold=pde)
    A, F = bc.apply(A, F, uh)
    uh[:] = spsolve(A, F).reshape(-1)
    errorMatrix[0, i] = space.integralalg.error(pde.solution, uh.value)
    errorMatrix[1, i] = space.integralalg.error(pde.gradient, uh.grad_value)
    # eta = residual_estimate(uh, pde.source)
    # eta = recovery_estimate(uh)
    # errorMatrix[2, i] = np.sqrt(np.sum(eta ** 2))

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

# 画函数图像
fig = plt.figure()
axes = fig.gca(projection='3d')
uh.add_plot(axes, cmap='rainbow')
Exemple #13
0
    print("The {}-th computation:".format(i))

    space = LagrangeFiniteElementSpace(mesh, p=p)

    pBS = periodicBoundarySettings(mesh, space.dof, set_periodic_edge_func)
    DirEdgeInd = pBS.idxNotPeriodicEdge
    periodicDof0, periodicDof1, dirDof = pBS.set_boundaryDofs()

    # |--- test
    # pdof = np.concatenate([periodicDof0, periodicDof1])
    # print('pdof = ', pdof)
    # bddof, = np.nonzero(space.boundary_dof())
    # print('diff_pdof = ', np.setdiff1d(bddof, pdof))

    NDof[i] = space.number_of_global_dofs()
    bc = DirichletBC(space, pde.dirichlet, threshold=DirEdgeInd)

    uh = space.function()
    A = space.stiff_matrix()

    F = space.source_vector(pde.source)

    A, F = bc.apply(A, F, uh)

    F, A = pBS.set_periodicAlgebraicSystem(periodicDof0,
                                           periodicDof1,
                                           F,
                                           lhsM=A)

    uh[:] = spsolve(A, F).reshape(-1)
    '$|| u - u_h||_{\Omega,0}$',  # L2 误差
    '$||\\nabla u - \\nabla u_h||_{\Omega, 0}$'  # H1 误差
]
errorMatrix = np.zeros((2, maxit), dtype=np.float)
NDof = np.zeros(maxit, dtype=np.float)

# 初始网格
fig = plt.figure()
axes = fig.gca()
mesh.add_plot(axes)

for i in range(maxit):
    space = LagrangeFiniteElementSpace(mesh, p=p)  # 建立有限元空间

    NDof[i] = space.number_of_global_dofs()  # 有限元空间自由度的个数
    bc = DirichletBC(space, pde.dirichlet)  # DirichletBC 条件

    uh = space.function()  # 有限元函数
    A = space.stiff_matrix()  # 刚度矩阵
    F = space.source_vector(pde.source)  # 载荷向量

    A, F = bc.apply(A, F, uh)  # 处理边界条件

    uh[:] = spsolve(A, F).reshape(-1)  # 稀疏矩阵直接解法器

    #ml = pyamg.ruge_stuben_solver(A)  # 代数多重网格解法器
    #uh[:] = ml.solve(F, tol=1e-12, accel='cg').reshape(-1)

    errorMatrix[0, i] = space.integralalg.L2_error(pde.solution,
                                                   uh)  # 计算 L2 误差
    errorMatrix[1, i] = space.integralalg.L2_error(pde.gradient,
Exemple #15
0
    def decoupled_NS_Solver_T1stOrder(self, vel0, vel1, ph, uh, uh_last, next_t):
        """
        The decoupled-Navier-Stokes-solver for the all system.
        :param vel0: The fist-component of velocity: stored the n-th(time) value, and to update the (n+1)-th value.
        :param vel1: The second-component of velocity: stored the n-th(time) value, and to update the (n+1)-th value.
        :param ph: The pressure: stored the n-th(time) value, and to update the (n+1)-th value.
        :param uh: The n-th(time) value of the solution of Cahn-Hilliard equation.
        :param uh_last: The (n-1)-th(time) value of the solution of Cahn-Hilliard equation.
        :param next_t: The next-time.
        :return: Updated vel0, vel1, ph.

        注意:
        本程序所参考的数值格式是按照 $D(u)=\nabla u + \nabla u^T$ 来写的,
        如果要调整为 $D(u)=(\nabla u + \nabla u^T)/2$, 需要调整的地方太多了,
        所以为了保证和数值格式的一致性, 应 `尽量避免` 使用 'self.stressC=0.5',
        以保持程序也是严格按照 $D(u)=\nabla u + \nabla u^T$ 的形式给出.
        """

        pde = self.pde
        # # variable coefficients settings
        m = pde.m
        rho0 = pde.rho0
        rho1 = pde.rho1
        nu0 = pde.nu0
        nu1 = pde.nu1

        rho_min = min(rho0, rho1)
        eta_max = max(nu0 / rho0, nu1 / rho1)
        J0 = -1. / 2 * (rho0 - rho1) * m

        nDir_NS = self.nDir_NS  # (NDir,GD), here, the GD is 2

        # # the pre-settings
        grad_vel0_f = self.uh_grad_value_at_faces(vel0, self.f_bcs, self.DirCellIdx_NS, self.DirLocalIdx_NS,
                                                  space=self.vspace)  # grad_vel0: (NQ,NDir,GD)
        grad_vel1_f = self.uh_grad_value_at_faces(vel1, self.f_bcs, self.DirCellIdx_NS, self.DirLocalIdx_NS,
                                                  space=self.vspace)  # grad_vel1: (NQ,NDir,GD)

        # for cell-integration
        grad_ph_val = self.space.grad_value(ph, self.c_bcs)  # (NQ,NC,GD)
        uh_val = self.space.value(uh, self.c_bcs)  # (NQ,NC)
        uh_val_f = self.space.value(uh, self.f_bcs)[..., self.DirEdgeIdx_NS]  # (NQ,NDir)
        #    |___ TODO: 为什么是 [..., self.DirCellIdx_NS] 而不是 [..., self.DirEdgeIdx_NS]?? 应该是个 bug ??
        #              |___ TODO: 2022-03-08 改为 [..., self.DirEdgeIdx_NS]
        grad_uh_val = self.space.grad_value(uh, self.c_bcs)  # (NQ,NC,GD)
        vel0_val = self.vspace.value(vel0, self.c_bcs)  # (NQ,NC)
        vel1_val = self.vspace.value(vel1, self.c_bcs)  # (NQ,NC)
        grad_vel0_val = self.vspace.grad_value(vel0, self.c_bcs)  # (NQ,NC,GD)
        grad_vel1_val = self.vspace.grad_value(vel1, self.c_bcs)  # (NQ,NC,GD)

        nolinear_val = self.NSNolinearTerm(vel0, vel1, self.c_bcs)  # nolinear_val.shape: (NQ,NC,GD)
        # nolinear_val0 = nolinear_val[..., 0]  # (NQ,NC)
        # nolinear_val1 = nolinear_val[..., 1]  # (NQ,NC)

        velDir_val = self.pde.dirichlet_NS(self.f_pp_Dir_NS, next_t)  # (NQ,NDir,GD)
        f_val_NS = self.pde.source_NS(self.c_pp, next_t, self.pde.epsilon, self.pde.eta, m, rho0, rho1, nu0, nu1, self.stressC)  # (NQ,NC,GD)
        # Neumann_0 = self.pde.neumann_0_NS(self.f_pp_Neu_NS, next_t, self.nNeu_NS)  # (NQ,NE)
        # Neumann_1 = self.pde.neumann_1_NS(self.f_pp_Neu_NS, next_t, self.nNeu_NS)  # (NQ,NE)

        # --- the CH_term: uh_val * (-epsilon*\nabla\Delta uh_val + \nabla free_energy)
        grad_free_energy_c = self.pde.epsilon / self.pde.eta ** 2 * self.grad_free_energy_at_cells(uh_last, self.c_bcs)  # (NQ,NC,2)
        if self.p < 3:
            grad_x_laplace_uh = np.zeros(grad_free_energy_c[..., 0].shape)
            grad_y_laplace_uh = np.zeros(grad_free_energy_c[..., 0].shape)
            CH_term_val0 = uh_val * grad_free_energy_c[..., 0]  # (NQ,NC)
            CH_term_val1 = uh_val * grad_free_energy_c[..., 1]  # (NQ,NC)
        elif self.p == 3:
            phi_xxx, phi_yyy, phi_yxx, phi_xyy = self.cb.get_highorder_diff(self.c_bcs, order='3rd-order')  # (NQ,NC,ldof)
            grad_x_laplace_uh = -self.pde.epsilon * np.einsum('ijk, jk->ij', phi_xxx + phi_xyy, uh[self.cell2dof])  # (NQ,NC)
            grad_y_laplace_uh = -self.pde.epsilon * np.einsum('ijk, jk->ij', phi_yxx + phi_yyy, uh[self.cell2dof])  # (NQ,NC)
            CH_term_val0 = uh_val * (grad_x_laplace_uh + grad_free_energy_c[..., 0])  # (NQ,NC)
            CH_term_val1 = uh_val * (grad_y_laplace_uh + grad_free_energy_c[..., 1])  # (NQ,NC)
        else:
            raise ValueError("The polynomial order p should be <= 3.")

        # --- update the variable coefficients
        rho_n = (rho0 + rho1) / 2. + (rho0 - rho1) / 2. * uh_val  # (NQ,NC)
        rho_n_f = (rho0 + rho1) / 2. + (rho0 - rho1) / 2. * uh_val_f  # (NQ,NDir)
        nu_n = (nu0 + nu1) / 2. + (nu0 - nu1) / 2. * uh_val  # (NQ,NC)
        nu_n_f = (nu0 + nu1) / 2. + (nu0 - nu1) / 2. * uh_val_f  # (NQ,NDir)
        J_n0 = J0 * (grad_x_laplace_uh + grad_free_energy_c[..., 0])  # (NQ,NC)
        J_n1 = J0 * (grad_y_laplace_uh + grad_free_energy_c[..., 1])  # (NQ,NC)

        # --- the auxiliary variable: G_VC
        stressC = self.stressC
        vel_stress_mat = [[stressC*2*grad_vel0_val[..., 0], stressC*(grad_vel0_val[..., 1] + grad_vel1_val[..., 0])],
                          [stressC*(grad_vel0_val[..., 1] + grad_vel1_val[..., 0]), stressC*2*grad_vel1_val[..., 1]]]
        vel_grad_mat = [[grad_vel0_val[..., 0], grad_vel0_val[..., 1]],
                        [grad_vel1_val[..., 0], grad_vel1_val[..., 1]]]
        rho_n_axis = rho_n[..., np.newaxis]
        G_VC = (-nolinear_val + (1. / rho_min - 1. / rho_n_axis) * grad_ph_val
                + 1. / rho_n_axis * self.vec_div_mat((nu0 - nu1) / 2. * grad_uh_val, vel_stress_mat)
                - 1. / rho_n_axis * np.array([CH_term_val0, CH_term_val1]).transpose((1, 2, 0))
                - 1. / rho_n_axis * self.vec_div_mat([J_n0, J_n1], vel_grad_mat) + 1. / rho_n_axis * f_val_NS
                + 1./self.dt * np.array([vel0_val, vel1_val]).transpose((1, 2, 0)))  # (NQ,NC,2)

        eta_n = nu_n / rho_n  # (NQ,NC)
        eta_n_f = nu_n_f / rho_n_f  # (NQ,NDir)
        eta_nx = ((nu0 - nu1) / 2. * rho_n - (rho0 - rho1) / 2. * nu_n) * grad_uh_val[..., 0] / rho_n ** 2  # (NQ,NC)
        eta_ny = ((nu0 - nu1) / 2. * rho_n - (rho0 - rho1) / 2. * nu_n) * grad_uh_val[..., 1] / rho_n ** 2  # (NQ,NC)
        curl_vel = stressC * (grad_vel1_val[..., 0] - grad_vel0_val[..., 1])  # (NQ,NC)
        curl_vel_f = stressC * (grad_vel1_f[..., 0] - grad_vel0_f[..., 1])  # (NQ,NDir)

        # for Dirichlet faces integration
        dir_int0 = -1 / self.dt * np.einsum('i, ijk, jk, ijn, j->jn', self.f_ws, velDir_val, nDir_NS, self.phi_f,
                                            self.DirEdgeMeasure_NS)  # (NDir,fldof)
        dir_int1 = -(np.einsum('i, j, ij, jin, j->jn', self.f_ws, nDir_NS[:, 1], eta_n_f*curl_vel_f, self.gphi_f[..., 0],
                               self.DirEdgeMeasure_NS)
                     + np.einsum('i, j, ij, jin, j->jn', self.f_ws, -nDir_NS[:, 0], eta_n_f*curl_vel_f, self.gphi_f[..., 1],
                                 self.DirEdgeMeasure_NS))  # (NDir,cldof)

        # for cell integration
        cell_int0 = np.einsum('i, ijs, ijks, j->jk', self.c_ws, G_VC, self.gphi_c, self.cellmeasure)  # (NC,cldof)
        cell_int1 = (np.einsum('i, ij, ijk, j->jk', self.c_ws, eta_ny * curl_vel, self.gphi_c[..., 0], self.cellmeasure)
                     + np.einsum('i, ij, ijk, j->jk', self.c_ws, -eta_nx * curl_vel, self.gphi_c[..., 1], self.cellmeasure))  # (NC,cldof)

        # # --- 1. assemble the NS's pressure equation
        prv = np.zeros((self.dof.number_of_global_dofs(),), dtype=self.ftype)  # (Npdof,) the Pressure's Right-hand Vector
        np.add.at(prv, self.face2dof[self.DirEdgeIdx_NS, :], dir_int0)
        np.add.at(prv, self.cell2dof[self.DirCellIdx_NS, :], dir_int1)
        np.add.at(prv, self.cell2dof, cell_int0 + cell_int1)

        # # --- 2. solve the NS's pressure equation
        plsm = 1. / rho_min * self.StiffMatrix

        # # Method I: The following code is right! Pressure satisfies \int_\Omega p = 0
        basis_int = self.space.integral_basis()
        plsm_temp = bmat([[plsm, basis_int.reshape(-1, 1)], [basis_int, None]], format='csr')
        prv = np.r_[prv, 0]
        ph[:] = spsolve(plsm_temp, prv)[:-1]  # we have added one additional dof
        # ph[:] = spsolve(plsm, prv)

        # # Method II: Using the Dirichlet boundary of pressure
        # def dir_pressure(p):
        #     return self.pde.pressure_NS(p, next_t)
        # bc = DirichletBC(self.space, dir_pressure)
        # plsm_temp, prv = bc.apply(plsm.copy(), prv)
        # ph[:] = spsolve(plsm_temp, prv).reshape(-1)

        # # ------------------------------------ # #
        # # --- to update the velocity value --- # #
        # # ------------------------------------ # #
        grad_ph = self.space.grad_value(ph, self.c_bcs)  # (NQ,NC,2)

        # # the Velocity-Left-Matrix
        vlm0 = 1 / self.dt * self.vel_MM + stressC * eta_max * self.vel_SM
        vlm1 = vlm0.copy()

        # # to get the u's Right-hand Vector
        def dir_u0(p):
            return self.pde.dirichlet_NS(p, next_t)[..., 0]

        def dir_u1(p):
            return self.pde.dirichlet_NS(p, next_t)[..., 1]

        # # --- assemble the first-component of Velocity-Right-Vector
        vrv0 = np.zeros((self.vdof.number_of_global_dofs(),), dtype=self.ftype)  # (Nvdof,)
        vrv0_c_0 = np.einsum('i, ij, ijk, j->jk', self.c_ws, - 1. / rho_min * grad_ph[..., 0] + G_VC[..., 0], self.vphi_c,
                             self.cellmeasure)  # (NC,clodf)
        vrv0_c_1 = (np.einsum('i, ij, ijk, j->jk', self.c_ws, (eta_n - eta_max) * curl_vel, self.vgphi_c[..., 1], self.cellmeasure)
                    + np.einsum('i, ij, ijk, j->jk', self.c_ws, eta_ny * curl_vel, self.vphi_c, self.cellmeasure))  # (NC,clodf)
        np.add.at(vrv0, self.vcell2dof, vrv0_c_0 + vrv0_c_1)

        v0_bc = DirichletBC(self.vspace, dir_u0, threshold=self.DirEdgeIdx_NS)
        vlm0, vrv0 = v0_bc.apply(vlm0, vrv0)
        vel0[:] = spsolve(vlm0, vrv0).reshape(-1)

        # # --- assemble the second-component of Velocity-Right-Vector
        vrv1 = np.zeros((self.vdof.number_of_global_dofs(),), dtype=self.ftype)  # (Nvdof,)
        vrv1_c_0 = np.einsum('i, ij, ijk, j->jk', self.c_ws, - 1. / rho_min * grad_ph[..., 1] + G_VC[..., 1], self.vphi_c,
                             self.cellmeasure)  # (NC,clodf)
        vrv1_c_1 = (np.einsum('i, ij, ijk, j->jk', self.c_ws, (eta_n - eta_max) * curl_vel, -self.vgphi_c[..., 0], self.cellmeasure)
                    + np.einsum('i, ij, ijk, j->jk', self.c_ws, - eta_nx * curl_vel, self.vphi_c, self.cellmeasure))  # (NC,clodf)
        np.add.at(vrv1, self.vcell2dof, vrv1_c_0 + vrv1_c_1)

        v1_bc = DirichletBC(self.vspace, dir_u1, threshold=self.DirEdgeIdx_NS)
        vlm1, vrv0 = v1_bc.apply(vlm1, vrv1)
        vel1[:] = spsolve(vlm1, vrv1).reshape(-1)
from fealpy.pde.linear_elasticity_model import BoxDomainData3d
from fealpy.functionspace import LagrangeFiniteElementSpace
from fealpy.functionspace import CrouzeixRaviartFiniteElementSpace
from fealpy.boundarycondition import DirichletBC

import pyamg
from timeit import default_timer as timer

n = int(sys.argv[1])

pde = BoxDomainData3d()
mesh = pde.init_mesh(n=n)

space = LagrangeFiniteElementSpace(mesh, p=1)
bc = DirichletBC(space, pde.dirichlet, threshold=pde.is_dirichlet_boundary)
uh = space.function(dim=3)
A = space.linear_elasticity_matrix(pde.lam, pde.mu, q=1)
F = space.source_vector(pde.source, dim=3)
A, F = bc.apply(A, F, uh)

if False:
    uh.T.flat[:] = spsolve(A, F)
elif False:
    N = len(F)
    print(N)
    start = timer()
    ilu = spilu(A.tocsc(), drop_tol=1e-6, fill_factor=40)
    end = timer()
    print('time:', end - start)
NDof = np.zeros((maxit, ), dtype=np.int_)
errorMatrix = np.zeros((len(errorType), maxit), dtype=np.float64)

mesh.add_plot(plt)
plt.savefig('./test-0.png')
plt.close()

for i in range(maxit):
    print('step:', i)
    space = LagrangeFiniteElementSpace(mesh, p=p)
    A = space.stiff_matrix(q=1)
    F = space.source_vector(pde.source)

    NDof[i] = space.number_of_global_dofs()
    bc = DirichletBC(space, pde.dirichlet)

    uh = space.function()
    A, F = bc.apply(A, F, uh)
    uh[:] = spsolve(A, F)

    errorMatrix[0, i] = space.integralalg.error(pde.solution,
                                                uh.value,
                                                power=2)
    errorMatrix[1, i] = space.integralalg.error(pde.gradient,
                                                uh.grad_value,
                                                power=2)
    errorMatrix[2, i] = space.integralalg.error(pde.gradient,
                                                rguh.value,
                                                power=2)
    eta = space.recovery_estimate(uh)
Exemple #18
0
    def NS_VC_Solver(self):
        """
        The Navier-Stokes Velocity-Correction scheme solver.
        """
        pde = self.pde
        dt = self.dt
        uh0 = self.uh0
        uh1 = self.uh1
        ph = self.ph
        vspace = self.vspace
        pspace = self.pspace
        vdof = self.vdof
        pdof = self.pdof
        pface2dof = pdof.face_to_dof()  # (NE,fldof)
        pcell2dof = pdof.cell_to_dof()  # (NC,cldof)
        ucell2dof = vspace.cell_to_dof()  # (NC,cldof)

        idxDirEdge = self.set_Dirichlet_edge()
        cellidxDir = self.mesh.ds.edge2cell[idxDirEdge, 0]
        localidxDir = self.mesh.ds.edge2cell[idxDirEdge, 2]

        Dir_face2dof = pface2dof[idxDirEdge, :]  # (NDir,flodf)
        Dir_cell2dof = pcell2dof[cellidxDir, :]  # (NDir,cldof)
        n_Dir = self.mesh.face_unit_normal(index=idxDirEdge)  # (NDir,2)
        dir_face_measure = self.mesh.entity_measure(
            'face', index=idxDirEdge)  # (NDir,2)
        cell_measure = self.mesh.cell_area()
        dir_cell_measure = self.mesh.cell_area(cellidxDir)

        f_q = self.integralalg.faceintegrator
        f_bcs, f_ws = f_q.get_quadrature_points_and_weights(
        )  # f_bcs.shape: (NQ,(GD-1)+1)
        f_pp = self.mesh.bc_to_point(
            f_bcs, index=idxDirEdge
        )  # f_pp.shape: (NQ,NDir,GD) the physical Gauss points

        c_q = self.integralalg.cellintegrator
        c_bcs, c_ws = c_q.get_quadrature_points_and_weights(
        )  # c_bcs.shape: (NQ,GD+1)
        c_pp = self.mesh.bc_to_point(
            c_bcs)  # c_pp.shape: (NQ_cell,NC,GD) the physical Gauss points

        last_uh0 = vspace.function()
        last_uh1 = vspace.function()
        next_ph = pspace.function()

        # # t^{n+1}: Pressure-Left-StiffMatrix
        plsm = self.pspace.stiff_matrix()
        basis_int = pspace.integral_basis()
        p_phi = pspace.face_basis(
            f_bcs)  # (NQ,1,fldof). 实际上这里可以直接用 pspace.basis(f_bcs), 两个函数的代码是相同的
        p_gphi_f = pspace.edge_grad_basis(f_bcs, cellidxDir,
                                          localidxDir)  # (NDir,NQ,cldof,GD)
        p_gphi_c = pspace.grad_basis(c_bcs)  # (NQ_cell,NC,ldof,GD)

        # # t^{n+1}: Velocity-Left-MassMatrix and -StiffMatrix
        ulmm = self.vspace.mass_matrix()
        ulsm = self.vspace.stiff_matrix()
        u_phi = vspace.basis(c_bcs)  # (NQ,1,cldof)

        next_t = 0
        dofLocalIdxInflow, localIdxInflow = self.set_velocity_inflow_dof()
        idxOutFlowEdge = self.set_outflow_edge()
        for nt in range(int(self.T / dt)):
            curr_t = nt * dt
            next_t = curr_t + dt

            # ---------------------------------------
            # 1st-step: get the p^{n+1}
            # ---------------------------------------
            # # Pressure-Right-Matrix
            if curr_t == 0.:
                # for Dirichlet-face-integration
                last_gu_val0 = pde.grad_velocity0(f_pp,
                                                  0)  # grad_u0: (NQ,NDir,GD)
                last_gu_val1 = pde.grad_velocity1(f_pp,
                                                  0)  # grad_u1: (NQ,NDir,GD)

                # for cell-integration
                last_u_val = pde.velocityInitialValue(c_pp)  # (NQ,NC,GD)
                last_u_val0 = last_u_val[..., 0]  # (NQ,NC)
                last_u_val1 = last_u_val[..., 1]  # (NQ,NC)

                last_nolinear_val0 = pde.NS_nolinearTerm_0(c_pp, 0)  # (NQ,NC)
                last_nolinear_val1 = pde.NS_nolinearTerm_1(c_pp, 0)  # (NQ,NC)
            else:
                # for Dirichlet-face-integration
                # last_gu_val0 = vspace.grad_value(last_uh0, f_bcs)  # grad_u0: (NQ,NDir,GD)
                # last_gu_val1 = vspace.grad_value(last_uh1, f_bcs)  # grad_u1: (NQ,NDir,GD)
                last_gu_val0 = self.uh_grad_value_at_faces(
                    last_uh0, f_bcs, cellidxDir,
                    localidxDir)  # grad_u0: (NQ,NDir,GD)
                last_gu_val1 = self.uh_grad_value_at_faces(
                    last_uh1, f_bcs, cellidxDir,
                    localidxDir)  # grad_u0: (NQ,NDir,GD)

                # for cell-integration
                last_u_val0 = vspace.value(last_uh0, c_bcs)  # (NQ,NC)
                last_u_val1 = vspace.value(last_uh1, c_bcs)

                last_nolinear_val = self.NSNolinearTerm(
                    last_uh0, last_uh1,
                    c_bcs)  # last_nolinear_val.shape: (NQ,NC,GD)
                last_nolinear_val0 = last_nolinear_val[..., 0]  # (NQ,NC)
                last_nolinear_val1 = last_nolinear_val[..., 1]  # (NQ,NC)

            uDir_val = pde.dirichlet(
                f_pp, next_t, bd_threshold=localIdxInflow)  # (NQ,NDir,GD)
            f_val = pde.source(c_pp, next_t)  # (NQ,NC,GD)

            # # --- to update the pressure value --- # #
            # # to get the Pressure's Right-hand Vector
            prv = np.zeros((pdof.number_of_global_dofs(), ),
                           dtype=self.ftype)  # (Npdof,)

            # for Dirichlet faces integration
            dir_int0 = -1 / dt * np.einsum('i, ijk, jk, ijn, j->jn', f_ws,
                                           uDir_val, n_Dir, p_phi,
                                           dir_face_measure)  # (NDir,fldof)
            dir_int1 = -pde.nu * (
                np.einsum('i, j, ij, jin, j->jn', f_ws, n_Dir[:, 1],
                          last_gu_val1[..., 0] - last_gu_val0[..., 1],
                          p_gphi_f[..., 0], dir_face_measure) +
                np.einsum('i, j, ij, jin, j->jn', f_ws, -n_Dir[:, 0],
                          last_gu_val1[..., 0] - last_gu_val0[..., 1],
                          p_gphi_f[..., 1], dir_face_measure))  # (NDir,cldof)
            # for cell integration
            cell_int0 = 1 / dt * (
                np.einsum('i, ij, ijk, j->jk', c_ws, last_u_val0,
                          p_gphi_c[..., 0], cell_measure) +
                np.einsum('i, ij, ijk, j->jk', c_ws, last_u_val1,
                          p_gphi_c[..., 1], cell_measure))  # (NC,cldof)
            cell_int1 = -(
                np.einsum('i, ij, ijk, j->jk', c_ws, last_nolinear_val0,
                          p_gphi_c[..., 0], cell_measure) +
                np.einsum('i, ij, ijk, j->jk', c_ws, last_nolinear_val1,
                          p_gphi_c[..., 1], cell_measure))  # (NC,cldof)
            cell_int2 = (np.einsum('i, ij, ijk, j->jk', c_ws, f_val[..., 0],
                                   p_gphi_c[..., 0], cell_measure) +
                         np.einsum('i, ij, ijk, j->jk', c_ws, f_val[..., 1],
                                   p_gphi_c[..., 1], cell_measure)
                         )  # (NC,cldof)

            np.add.at(prv, Dir_face2dof, dir_int0)
            np.add.at(prv, Dir_cell2dof, dir_int1)
            np.add.at(prv, pcell2dof, cell_int0 + cell_int1 + cell_int2)

            # # Method I: The following code is right! Pressure satisfies \int_\Omega p = 0
            # plsm_temp = bmat([[plsm, basis_int.reshape(-1, 1)], [basis_int, None]], format='csr')
            # prv = np.r_[prv, 0]
            # next_ph[:] = spsolve(plsm_temp, prv)[:-1]  # we have added one addtional dof

            # # Method II: Using the Dirichlet boundary of pressure
            def dir_pressure(p):
                return pde.pressure_dirichlet(p, next_t)

            bc = DirichletBC(pspace, dir_pressure, threshold=idxOutFlowEdge)
            plsm_temp, prv = bc.apply(plsm.copy(), prv)
            next_ph[:] = spsolve(plsm_temp, prv).reshape(-1)

            # # --- to update the velocity value --- # #
            next_gradph = pspace.grad_value(next_ph, c_bcs)  # (NQ,NC,2)

            # the velocity u's Left-Matrix
            ulm0 = 1 / dt * ulmm + pde.nu * ulsm
            ulm1 = 1 / dt * ulmm + pde.nu * ulsm

            # # to get the u's Right-hand Vector
            def dir_u0(p):
                return pde.dirichlet(p, next_t,
                                     bd_threshold=dofLocalIdxInflow)[..., 0]

            def dir_u1(p):
                return pde.dirichlet(p, next_t,
                                     bd_threshold=dofLocalIdxInflow)[..., 1]

            # for the first-component of velocity
            urv0 = np.zeros((vdof.number_of_global_dofs(), ),
                            dtype=self.ftype)  # (Nvdof,)
            urv0_temp = np.einsum('i, ij, ijk, j->jk', c_ws,
                                  last_u_val0 / dt - next_gradph[..., 0] -
                                  last_nolinear_val0 + f_val[..., 0], u_phi,
                                  cell_measure)  # (NC,clodf)
            np.add.at(urv0, ucell2dof, urv0_temp)
            u0_bc = DirichletBC(vspace, dir_u0, threshold=idxDirEdge)
            ulm0, urv0 = u0_bc.apply(ulm0, urv0)
            last_uh0[:] = spsolve(ulm0, urv0).reshape(-1)

            # for the second-component of velocity
            urv1 = np.zeros((vdof.number_of_global_dofs(), ),
                            dtype=self.ftype)  # (Nvdof,)
            urv1_temp = np.einsum('i, ij, ijk, j->jk', c_ws,
                                  last_u_val1 / dt - next_gradph[..., 1] -
                                  last_nolinear_val1 + f_val[..., 1], u_phi,
                                  cell_measure)  # (NC,clodf)
            np.add.at(urv1, ucell2dof, urv1_temp)
            u1_bc = DirichletBC(vspace, dir_u1, threshold=idxDirEdge)
            ulm1, urv1 = u1_bc.apply(ulm1, urv1)
            last_uh1[:] = spsolve(ulm1, urv1).reshape(-1)

            if nt % 100 == 0:
                print('# ------------ logging the circle info ------------ #')
                print('current t = ', curr_t)
                p_l2err, u0_l2err, u1_l2err = self.currt_error(
                    next_ph, last_uh0, last_uh1, next_t)
                print('p_l2err = %e,  u0_l2err = %e,  u1_l2err = %e' %
                      (p_l2err, u0_l2err, u1_l2err))
                print(
                    '# ------------------------------------------------- # \n')
                if np.isnan(p_l2err) | np.isnan(u0_l2err) | np.isnan(u1_l2err):
                    print('Some error is nan: breaking the program')
                    break

            # print('end of current time')

        # print('# ------------ the end error ------------ #')
        # p_l2err, u0_l2err, u1_l2err = self.currt_error(next_ph, last_uh0, last_uh1, next_t)
        # print('p_l2err = %e,  u0_l2err = %e,  u1_l2err = %e' % (p_l2err, u0_l2err, u1_l2err))

        return last_uh0, last_uh1, next_ph
Exemple #19
0
    return bmat([[I, P]])


box = [0, 1, 0, 1]
n = 6 
model = CosCosData()
mesh = rectangledomainmesh(box, nx=2**n, ny=2**n, meshtype='tri') 
N = mesh.number_of_points()
V = function_space(mesh, 'Lagrange', 1)
point = V.interpolation_points()

uh = FiniteElementFunction(V)
a  = LaplaceSymetricForm(V, 3)
L = SourceForm(V, model.source, 3)
bc = DirichletBC(V, model.dirichlet, model.is_boundary)

A = a.get_matrix()
b = L.get_vector()
A, b = bc.apply(A, b)

PI = prolongate_matrix(mesh, n)
AA = PI.transpose()@A@PI
bb = PI.transpose()@b

DL = tril(AA).tocsc()
DLInv = inv(DL)
U = triu(AA, 1)

x0 = np.zeros(N+n-1, dtype=np.float)
 def apply_boundary_condition(self, A, b, timeline):
     t1 = timeline.next_time_level()
     bc = DirichletBC(self.space, lambda x:self.pde.dirichlet(x, t1))
     A, b = bc.apply(A, b)
     return A, b
Exemple #21
0
        # t1 时间层的右端项
        @cartesian
        def source(p):
            return pde.source(p, t1)

        F = space.source_vector(source)
        F *= dt
        F += M @ uh0

        # t1 时间层的 Dirichlet 边界条件处理
        @cartesian
        def dirichlet(p):
            return pde.dirichlet(p, t1)

        bc = DirichletBC(space, dirichlet)
        GD, F = bc.apply(G, F, uh1)

        # 代数系统求解
        uh1[:] = spsolve(GD, F)
        eta = space.recovery_estimate(uh1, method='area_harmonic')
        err = np.sqrt(np.sum(eta**2))
        print('errrefine', err)
        if err < tol:
            break
        else:
            # 加密并插值
            NN0 = smesh.number_of_nodes()
            edge = smesh.entity('edge')
            isMarkedCell = smesh.refine_marker(eta, rtheta, method='L2')
            smesh.refine_triangle_rg(isMarkedCell)
Exemple #22
0
for i in range(maxit):
    print("The {}-th computation:".format(i))

    node = mesh.entity('node')
    cell = mesh.entity('cell')
    lmesh = LagrangeTriangleMesh(node, cell, p=p, surface=surface)
    space = IsoLagrangeFiniteElementSpace(lmesh, p=p)
    NDof[i] = space.number_of_global_dofs()
    print(NDof[i])

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

    # 封闭曲面,设置其第 0 个插值节点的值为真解值
    bc = DirichletBC(space, pde.solution)
    A, F = bc.apply(A, F, uh, threshold=np.array([0]))
    uh[:] = spsolve(A, F).reshape(-1)

    uI = space.interpolation(pde.solution)
    errorMatrix[0, i] = space.integralalg.error(pde.solution,
                                                uh.value,
                                                linear=False)
    errorMatrix[1, i] = space.integralalg.error(pde.gradient,
                                                uh.grad_value,
                                                linear=False)
    errorMatrix[2, i] = space.integralalg.error(pde.solution,
                                                uI.value,
                                                linear=False)
    errorMatrix[3, i] = space.integralalg.error(pde.gradient,
                                                uI.grad_value,
Exemple #23
0
n = int(sys.argv[1])
lam = float(sys.argv[2])
mu = float(sys.argv[3])
stype = sys.argv[4]

pde = PolyModel3d(lam=lam, mu=mu) 

mesh = pde.init_mesh(n=n)

NN = mesh.number_of_nodes()
print("NN:", 3*NN)

space = LagrangeFiniteElementSpace(mesh, p=1)

bc = DirichletBC(space, pde.dirichlet)

uh = space.function(dim=3)
A = space.linear_elasticity_matrix(pde.lam, pde.mu, q=1)
F = space.source_vector(pde.source, dim=3)
A, F = bc.apply(A, F, uh)

I = space.rigid_motion_matrix()
S = space.stiff_matrix(2*pde.mu)
S = bc.apply_on_matrix(S)

solver = LinearElasticityLFEMFastSolver_1(A, S, I, stype=stype, drop_tol=1e-6,
        fill_factor=40) 

solver.solve(uh, F)
error = space.integralalg.error(pde.displacement, uh)
Exemple #24
0
qt = 3

model = LShapeRSinData()
mesh = lshape_mesh(r=3)
maxit = 4
Ndof = np.zeros(maxit, dtype=np.int)
error = np.zeros(maxit, dtype=np.float)
H1error = np.zeros(maxit, dtype=np.float)
ratio = np.zeros(maxit, dtype=np.float)
for i in range(maxit):
    V = function_space(mesh, 'Lagrange', degree)
    uh = FiniteElementFunction(V)
    Ndof[i] = V.number_of_global_dofs()
    a = LaplaceSymetricForm(V, qt)
    L = SourceForm(V, model.source, qt)
    bc = DirichletBC(V, model.dirichlet)
    point = V.interpolation_points()
    solve(a, L, uh, dirichlet=bc, solver='direct')
    error[i] = L2_error(model.solution, uh, order=qt)
    H1error[i] = H1_semi_error(model.gradient, uh, order=qt)
    if i < maxit - 1:
        mesh.uniform_refine()

# 输出结果
ratio[1:] = error[0:-1] / error[1:]
print('Ndof:', Ndof)
print('error:', error)
print('ratio:', ratio)
print('H1semierror:', H1error)
print('ratio:', H1error[0:-1] / H1error[1:])
Exemple #25
0
maxit = int(sys.argv[2])

start = timer()
solver = MatlabSolver()
end = timer()

print("The matalb start time:", end - start)

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

for i in range(maxit):
    space = LagrangeFiniteElementSpace(mesh, p=1)
    gdof = space.number_of_global_dofs()
    print("The num of dofs:", gdof)
    A = space.stiff_matrix()
    b = space.source_vector(pde.source)
    bc = DirichletBC(space, pde.dirichlet)
    AD, b = bc.apply(A, b)
    uh0 = solver.divide(AD, b)
    start = timer()
    uh1 = spsolve(AD, b)
    end = timer()
    print("The spsolver time:", end - start)

    print(np.sum(np.abs(uh0 - uh1)))
    #uh1 = solver.mumps_solver(A, b)
    #uh2 = solver.ifem_amg_solver(A, b)
    if i < maxit - 1:
        mesh.uniform_refine()
Exemple #26
0
from fealpy.functionspace.tools import function_space
from fealpy.form.Form import LaplaceSymetricForm, MassForm, SourceForm
from fealpy.boundarycondition import DirichletBC
from fealpy.erroranalysis import L2_error
from fealpy.functionspace.function import FiniteElementFunction

model = SinCosExpData()
box = [0, 1, 0, 1]
n = 10
mesh = rectangledomainmesh(box, nx=n, ny=n, meshtype='tri')
V = function_space(mesh, 'Lagrange', 1)
Ndof = V.number_of_global_dofs()
A = LaplaceSymetricForm(V, 3).get_matrix()
M = MassForm(V, 3).get_matrix()
b = SourceForm(V, model.source, 1).get_vector()
BC = DirichletBC(V, model.dirichlet, model.is_dirichlet_boundary)

T0 = 0.0
T1 = 1
N = 400
dt = (T1 - T0) / N
print(dt)

uh = FiniteElementFunction(V)
uh[:] = model.init_value(V.interpolation_points())

uht = [uh]
MD = BC.apply_on_matrix(M)
for i in range(1, N + 1):
    t = T0 + i * dt