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 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)
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()
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) #
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)
# 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 # 隐式迭代矩阵
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()
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
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)