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 poisson_fem_2d_neuman_test(self, p=1): pde = CosCosData() mesh = pde.init_mesh(n=2) for i in range(4): space = LagrangeFiniteElementSpace(mesh, p=p) A = space.stiff_matrix() b = space.source_vector(pde.source) uh = space.function() bc = BoundaryCondition(space, neuman=pde.neuman) bc.apply_neuman_bc(b) c = space.integral_basis() AD = bmat([[A, c.reshape(-1, 1)], [c, None]], format='csr') bb = np.r_[b, 0] x = spsolve(AD, bb) uh[:] = x[:-1] area = np.sum(space.integralalg.cellmeasure) ubar = space.integralalg.integral(pde.solution, barycenter=False) / area def solution(p): return pde.solution(p) - ubar error = space.integralalg.L2_error(solution, uh) print(error) mesh.uniform_refine()
def solve_poisson_robin(self, p=1, n=1, plot=True): pde = XYData() mesh = pde.init_mesh(n=n) node = mesh.node cell = mesh.entity("cell") name = 'RobinBCTest.mat' space = LagrangeFiniteElementSpace(mesh, p=p) A = space.stiff_matrix() F = space.source_vector(pde.source) # print(A.toarray()) # A, F = space.set_robin_bc(A, F, pde.robin) uh = space.function() #bc = BoundaryCondition(space, robin=pde.robin) A, b = space.set_robin_bc(A, F, pde.robin) uh[:] = spsolve(A, b).reshape(-1) error = space.integralalg.L2_error(pde.solution, uh) print(error) # print('A:', A.toarray()) # print('F:', F) if plot: fig = plt.figure() axes = fig.gca() mesh.add_plot(axes) mesh.find_node(axes, showindex=True) mesh.find_cell(axes, showindex=True) plt.show()
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)
def poisson_fem_2d_test(self, p=1): pde = CosCosData() mesh = pde.init_mesh(n=3) for i in range(4): space = LagrangeFiniteElementSpace(mesh, p=p) A = space.stiff_matrix() b = space.source_vector(pde.source) uh = space.function() bc = BoundaryCondition(space, dirichlet=pde.dirichlet) A, b = bc.apply_dirichlet_bc(A, b, uh) uh[:] = spsolve(A, b).reshape(-1) error = space.integralalg.L2_error(pde.solution, uh) print(error) mesh.uniform_refine()
def solve_poisson_robin(self, p=1, n=1, plot=True): pde = CosCosCosData() mesh = pde.init_mesh(n=n) space = LagrangeFiniteElementSpace(mesh, p=p) A = space.stiff_matrix() F = space.source_vector(pde.source) uh = space.function() bc = BoundaryCondition(space, robin=pde.robin) A, b = space.set_robin_bc(A, F, pde.robin) uh[:] = spsolve(A, b).reshape(-1) 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 solve_poisson_robin(self, p=1, n=1, plot=True): pde = XYData() mesh = pde.init_mesh(n=1) space = LagrangeFiniteElementSpace(mesh, p=p) A = space.stiff_matrix() F = space.source_vector(pde.source) space.set_robin_bc(A, F, pde.robin) print('A:', A.toarray()) print('F:', F) if plot: fig = plt.figure() axes = fig.gca() mesh.add_plot(axes) mesh.find_node(axes, showindex=True) mesh.find_cell(axes, showindex=True) plt.show()
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)
pde = CosCosData() mesh = pde.init_mesh(n=3) 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() uh = space.function() A = space.stiff_matrix() F = space.source_vector(pde.source) bc = NeumannBC(space, pde.neumann) A, F = bc.apply( F, A=A) # Here is the case for pure Neumann bc, we also need modify A # bc.apply(F) # Not pure Neumann bc case uh[:] = spsolve(A, F)[:-1] # we add a addtional dof # Here can not work #ml = pyamg.ruge_stuben_solver(A) #x = ml.solve(F, tol=1e-12, accel='cg').reshape(-1) #uh[:] = x[-1] errorMatrix[0, i] = space.integralalg.L2_error(pde.solution, uh) errorMatrix[1, i] = space.integralalg.L2_error(pde.gradient, uh.grad_value)
import numpy as np from scipy.sparse.linalg import spsolve import matplotlib.pyplot as plt from fealpy.pde.linear_elasticity_model import HuangModel2d from fealpy.functionspace import LagrangeFiniteElementSpace from fealpy.boundarycondition import BoundaryCondition p = int(sys.argv[1]) n = int(sys.argv[2]) pde = HuangModel2d(lam=100000, mu=1.0) mu = pde.mu lam = pde.lam mesh = pde.init_mesh(n=n) space = LagrangeFiniteElementSpace(mesh, p=p) bc = BoundaryCondition(space, dirichlet=pde.dirichlet) uh = space.function(dim=2) #A = space.linear_elasticity_matrix(mu, lam) A = space.recovery_linear_elasticity_matrix(mu, lam) F = space.source_vector(pde.source, dim=2) A, F = bc.apply_dirichlet_bc(A, F, uh, is_dirichlet_boundary=pde.is_dirichlet_boundary) uh.T.flat[:] = spsolve(A, F) error = space.integralalg.L2_error(pde.displacement, uh) print(error)
M = space.mass_matrix(c=r) b = np.array([1.0, 1.0], dtype=np.float64) B = space.convection_matrix(c=b) @cartesian 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()
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