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
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()
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)
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
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()
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)
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
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()
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)
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')
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,
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)
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
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
# 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)
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,
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)
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:])
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()
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