def __init__(self, pde, timeline, n=1): self.pde = pde box = pde.domain() mf = MeshFactory() self.mesh = mf.boxmesh2d(box, nx=n, ny=n, meshtype='tri') self.uspace = RaviartThomasFiniteElementSpace2d(self.mesh, p=0) self.pspace = self.uspace.smspace self.timeline = timeline NL = timeline.number_of_time_levels() # state variable self.yh = self.pspace.function(dim=NL) self.uh = self.pspace.function(dim=NL) self.tph = self.uspace.function(dim=NL) self.ph = self.uspace.function() bc = self.mesh.entity_barycenter('cell') f = cartesian(lambda p: pde.y_solution(p, 0)) self.yh[:, 0] = self.pspace.local_projection(f) # costate variable self.zh = self.pspace.function(dim=NL) self.tqh = self.uspace.function(dim=NL) self.qh = self.uspace.function() self.A = self.uspace.stiff_matrix() # RT 质量矩阵 self.D = self.uspace.div_matrix() # (p, \div v) self.M = self.pspace.mass_matrix()
def __init__(self, pde, mesh, timeline): self.pde = pde self.mesh = mesh NC = mesh.number_of_cells() self.integrator = mesh.integrator(3, 'cell') self.bc = mesh.entity_barycenter('cell') self.ec = mesh.entity_barycenter('edge') self.cellmeasure = mesh.entity_measure('cell') self.uspace = RaviartThomasFiniteElementSpace2d(mesh, p=0) self.pspace = self.uspace.smspace self.timeline = timeline NL = timeline.number_of_time_levels() self.dt = timeline.current_time_step_length() # state variable self.yh = self.pspace.function(dim=NL) self.uh = self.pspace.function(dim=NL) self.tph = self.uspace.function(dim=NL) self.ph = self.uspace.function() self.yh[:, 0] = pde.y_solution(self.bc, 0) # costate variable self.zh = self.pspace.function(dim=NL) self.tqh = self.uspace.function(dim=NL) self.qh = self.uspace.function() self.A = self.uspace.stiff_matrix() # RT 质量矩阵 self.D = self.uspace.div_matrix() # TODO: 确定符号, 符号为正 data = self.cellmeasure * np.ones(NC, ) self.M = spdiags(data, 0, NC, NC)
def __init__(self, vdata, cdata, mesh, timeline, p=0, options={'rdir': '/home/why/result'}): self.options = options self.vdata = vdata self.cdata = cdata self.mesh = mesh self.timeline = timeline self.uspace = RaviartThomasFiniteElementSpace2d(mesh, p=p) self.cspace = ScaledMonomialSpace2d(mesh, p=p + 1) self.uh = self.uspace.function() # 速度场自由度数组 self.ph = self.uspace.smspace.function() # 压力场自由度数组 self.ch = self.cspace.function() # 浓度场自由度数组 # 初始浓度场设为 1 ldof = self.cspace.number_of_local_dofs() self.ch[0::ldof] = 1.0 self.M = self.cspace.cell_mass_matrix() self.H = inv(self.M) self.set_init_velocity_field() # 计算初始的速度场和压力场 # vtk 文件输出 node, cell, cellType, NC = self.mesh.to_vtk() self.points = vtk.vtkPoints() self.points.SetData(vnp.numpy_to_vtk(node)) self.cells = vtk.vtkCellArray() self.cells.SetCells(NC, vnp.numpy_to_vtkIdTypeArray(cell)) self.cellType = cellType
def __init__(self, pde, mesh, timeline): self.pde = pde self.mesh = mesh self.uspace = RaviartThomasFiniteElementSpace2d(mesh, p=0) self.pspace = self.uspace.smspace self.timeline = timeline NL = timeline.number_of_time_levels() # state variable self.yh = self.pspace.function(dim=NL) self.uh = self.pspace.function(dim=NL) self.tph = self.uspace.function(dim=NL) self.ph = self.uspace.function() f = cartesian(lambda p: pde.y_solution(p, 0)) self.yh[:, 0] = self.pspace.local_projection(f) # costate variable self.zh = self.pspace.function(dim=NL) self.tqh = self.uspace.function(dim=NL) self.qh = self.uspace.function() self.A = self.uspace.stiff_matrix() # RT 质量矩阵 self.D = self.uspace.div_matrix() # (p, \div v) self.M = self.pspace.mass_matrix()
def __init__(self): self.domain = [0, 50, 0, 50] self.mesh = MeshFactory().regular(self.domain, n=50) self.timeline = UniformTimeLine(0, 1, 100) self.space0 = RaviartThomasFiniteElementSpace2d(self.mesh, p=0) self.space1 = ScaledMonomialSpace2d(self.mesh, p=1) # 线性间断有限元空间 self.vh = self.space0.function() # 速度 self.ph = self.space0.smspace.function() # 压力 self.ch = self.space1.function(dim=3) # 三个组分的摩尔密度 self.options = { 'viscosity': 1.0, 'permeability': 1.0, 'temperature': 397, 'pressure': 50, 'porosity': 0.2, 'injecttion_rate': 0.1, 'compressibility': (0.001, 0.001, 0.001), 'pmv': (1.0, 1.0, 1.0), 'dt': self.timeline.dt } c = self.options['viscosity'] / self.options['permeability'] self.A = c * self.space0.mass_matrix() self.B = self.space0.div_matrix() phi = self.options['porosity'] self.M = phi / dt * self.space0.smspace.mass_matrix() # self.MC = self.space1.cell_mass_matrix() / dt
def mesh_with_fracture(self, plot=True): box = [0, 1, 0, 1] mesh = self.mf.boxmesh2d(box, nx=10, ny=10, meshtype='tri') def is_fracture(p): x = p[..., 0] y = p[..., 1] flag0 = (x == 0.5) & (y > 0.2) & (y < 0.8) flag1 = (y == 0.5) & (x > 0.2) & (x < 0.8) return flag0 | flag1 bc = mesh.entity_barycenter('edge') isFEdge = is_fracture(bc) mesh.edgedata['fracture'] = isFEdge NE = mesh.number_of_edges() print('边的个数:', NE) space = RaviartThomasFiniteElementSpace2d(mesh, p=0) gdof = space.number_of_global_dofs() print('gdof:', gdof) if plot: fig = plt.figure() axes = fig.gca() mesh.add_plot(axes) mesh.find_edge(axes, index=isFEdge, color='r') plt.show()
def show_basis(self): h = 0.5 box = [-h, 1+h, -h, np.sqrt(3)/2+h] mesh = self.meshfactory.one_triangle_mesh('equ') space = RaviartThomasFiniteElementSpace2d(mesh, p=2, q=2) fig = plt.figure() space.show_basis(fig, box=box) plt.show()
def show_basis(self, p=0): h = 0.5 box = [-h, 1 + h, -h, 1 + h] node = np.array([[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0]], dtype=np.float) cell = np.array([[1, 2, 0]], dtype=np.int) mesh = TriangleMesh(node, cell) space = RaviartThomasFiniteElementSpace2d(mesh, p=p) fig = plt.figure() space.show_basis(fig, box=box) cell = np.array([[3, 0, 2]], dtype=np.int) mesh = TriangleMesh(node, cell) space = RaviartThomasFiniteElementSpace2d(mesh, p=p) fig = plt.figure() space.show_basis(fig, box=box) print(space.bcoefs) plt.show()
def __init__(self, vdata, cdata, mesh, p=0): self.vdata = vdata self.cdata = cdata self.mesh = mesh self.space = RaviartThomasFiniteElementSpace2d(mesh, p=p) self.uh = self.space.function() # 速度场函数 self.ph = self.space.smspace.function() # 压力场函数 self.ch = self.space.smspace.function() # 浓度场函数 self.M = 0.2*self.space.smspace.cell_mass_matrix() self.H = inv(self.M) self.set_init_velocity_field() # 计算初始的速度场和压力场
def __init__(self, model): self.model = model self.mesh = model.space_mesh() self.timeline = model.time_mesh(n=3650) self.uspace = RaviartThomasFiniteElementSpace2d(self.mesh, p=0) self.cspace = ScaledMonomialSpace2d(self.mesh, p=1) # 线性间断有限元空间 self.uh = self.uspace.function() # 速度 self.ph = model.init_pressure(self.uspace.smspace) # 初始压力 # 三个组分的摩尔密度, 三个组分一起计算 self.ch = model.init_molar_density(self.cspace) # TODO:初始化三种物质的浓度 # 1 muPa*s = 1e-11 bar*s = 1e-11*24*3600 bar*d = 8.64e-07 bar*d # 1 md = 9.869 233e-16 m^2 self.options = { 'viscosity': 1.0, # 粘性系数 1 muPa*s = 1e-6 Pa*s, 1 cP = 10^{−3} Pa⋅s = 1 mPa⋅s 'permeability': 1.0, # 1 md 渗透率, 1 md = 9.869233e-16 m^2 'temperature': 397, # 初始温度 K 'pressure': 50, # bar 初始压力 'porosity': 0.2, # 孔隙度 'injecttion_rate': 0.1, # 注入速率 'compressibility': 0.001, #压缩率 'pmv': (1.0, 1.0, 1.0), # 偏摩尔体积 'rdir': '/home/why/result/test/', 'step': 1 } self.CM = self.cspace.cell_mass_matrix() self.H = inv(self.CM) c = 8.64 / 9.869233 * 1e+9 self.M = c * self.uspace.mass_matrix() self.B = -self.uspace.div_matrix() dt = self.timeline.dt c = self.options['porosity'] * self.options['compressibility'] / dt self.D = c * self.uspace.smspace.mass_matrix() # 压力边界条件 self.F0 = -self.uspace.set_neumann_bc(model.pressure_bc, threshold=model.is_pressure_bc) # vtk 文件输出 node, cell, cellType, NC = self.mesh.to_vtk() self.points = vtk.vtkPoints() self.points.SetData(vnp.numpy_to_vtk(node)) self.cells = vtk.vtkCellArray() self.cells.SetCells(NC, vnp.numpy_to_vtkIdTypeArray(cell)) self.cellType = cellType
def interpolation(self, n=0, p=0, plot=True): box = [-0.5, 1.5, -0.5, 1.5] pde = CosCosData() mesh = pde.init_mesh(n=n, meshtype='tri') space = RaviartThomasFiniteElementSpace2d(mesh, p=p) uI = space.interpolation(pde.flux) error = space.integralalg.L2_error(pde.flux, uI) print(error) if plot: fig = plt.figure() axes = fig.gca() mesh.add_plot(axes, box=box) plt.show()
def interpolation(self, n=0, p=0): pde = CosCosData() mesh = pde.init_mesh(n=n, meshtype='tri') space = RaviartThomasFiniteElementSpace2d(mesh, p=p) uI = space.interpolation(pde.flux) print(space.basis.coordtype) u = Function(space) u[:] = uI qf = mesh.integrator(3, 'cell') bcs, ws = qf.get_quadrature_points_and_weights() error = space.integralalg.L2_error(pde.source, u.div_value) print('error:', error) print(dir(u))
def __init__(self, model): self.model = model self.mesh = model.space_mesh() self.timeline = model.time_mesh() dt = self.timeline.current_time_step_length() self.space = RaviartThomasFiniteElementSpace2d(self.mesh, p=0) self.uh = self.space.function() self.ph = model.init_pressure(self.space.smspace) self.M = self.space.mass_matrix() self.B = -self.space.div_matrix() self.D = self.space.smspace.mass_matrix()/dt self.F0 = -self.space.set_neumann_bc(model.pressure_bc, threshold=model.is_pressure_bc) # vtk 文件输出 node, cell, cellType, NC = self.mesh.to_vtk() self.points = vtk.vtkPoints() self.points.SetData(vnp.numpy_to_vtk(node)) self.cells = vtk.vtkCellArray() self.cells.SetCells(NC, vnp.numpy_to_vtkIdTypeArray(cell)) self.cellType = cellType
def edge_basis(self, plot=True): pde = X2Y2Data() mesh = pde.init_mesh(n=0, meshtype='tri') space = RaviartThomasFiniteElementSpace2d(mesh, p=0) qf = mesh.integrator(3, 'edge') bcs, ws = qf.get_quadrature_points_and_weights() index = mesh.ds.boundary_edge_index() ps = mesh.bc_to_point(bcs, etype='edge', index=index) phi = space.edge_basis(bcs, index=index) if plot: box = [-0.5, 1.5, -0.5, 1.5] fig = plt.figure() axes = fig.gca() mesh.add_plot(axes, box=box) mesh.find_node(axes, showindex=True) mesh.find_edge(axes, showindex=True) mesh.find_cell(axes, showindex=True) node = ps.reshape(-1, 2) uv = phi.reshape(-1, 2) axes.quiver(node[:, 0], node[:, 1], uv[:, 0], uv[:, 1]) plt.show()
def __init__(self, model, T=800 * 3600 * 24, NS=32, NT=800 * 24): self.model = model self.mesh = model.space_mesh(n=NS) self.timeline = model.time_mesh(T=T, n=NT) self.GD = model.GD if self.GD == 2: self.vspace = RaviartThomasFiniteElementSpace2d(self.mesh, p=0) # 速度空间 elif self.GD == 3: self.vspace = RaviartThomasFiniteElementSpace3d(self.mesh, p=0) self.pspace = self.vspace.smspace # 压强和饱和度所属的空间, 分片常数 self.cspace = LagrangeFiniteElementSpace(self.mesh, p=1) # 位移空间 # 上一时刻物理量的值 self.v = self.vspace.function() # 速度函数 self.p = self.pspace.function() # 压强函数 self.s = self.pspace.function() # 水的饱和度函数 默认为0, 初始时刻区域内水的饱和度为0 self.u = self.cspace.function(dim=self.GD) # 位移函数 self.phi = self.pspace.function() # 孔隙度函数, 分片常数 # 当前时刻物理量的值, 用于保存临时计算出的值, 模型中系数的计算由当前时刻 # 的物理量的值决定 self.cv = self.vspace.function() # 速度函数 self.cp = self.pspace.function() # 压强函数 self.cs = self.pspace.function() # 水的饱和度函数 默认为0, 初始时刻区域内水的饱和度为0 self.cu = self.cspace.function(dim=self.GD) # 位移函数 self.cphi = self.pspace.function() # 孔隙度函数, 分片常数 # 初值 self.p[:] = model.rock['initial pressure'] # MPa self.phi[:] = model.rock['porosity'] # 初始孔隙度 self.cp[:] = model.rock['initial pressure'] # 初始地层压强 self.cphi[:] = model.rock['porosity'] # 当前孔隙度系数 # 源项, TODO: 注意这里假设用的是结构网格, 换其它的网格需要修改代码 self.fo = self.cspace.function() self.fo[-1] = -self.model.oil['production rate'] # 产出 self.fw = self.cspace.function() self.fw[0] = self.model.water['injection rate'] # 注入 # 一些常数矩阵和向量 # 速度散度矩阵, 速度方程对应的散度矩阵, (\nabla\cdot v, w) self.B = self.vspace.div_matrix() # 压强方程对应的位移散度矩阵, (\nabla\cdot u, w) 位移散度矩阵 # * 注意这里利用了压强空间分片常数, 线性函数导数也是分片常数的事实 c = self.mesh.entity_measure('cell') c *= self.model.rock['biot'] val = self.mesh.grad_lambda() # (NC, TD+1, GD) val *= c[:, None, None] pc2d = self.pspace.cell_to_dof() cc2d = self.cspace.cell_to_dof() pgdof = self.pspace.number_of_global_dofs() cgdof = self.cspace.number_of_global_dofs() I = np.broadcast_to(pc2d, shape=cc2d.shape) J = cc2d self.PU0 = csr_matrix((val[..., 0].flat, (I.flat, J.flat)), shape=(pgdof, cgdof)) self.PU1 = csr_matrix((val[..., 1].flat, (I.flat, J.flat)), shape=(pgdof, cgdof)) if self.GD == 3: self.PU2 = csr_matrix((val[..., 2].flat, (I.flat, J.flat)), shape=(pgdof, cgdof)) # 线弹性矩阵的右端向量 sigma0 = self.pspace.function() sigma0[:] = self.model.rock['initial stress'] self.FU = np.zeros(self.GD * cgdof, dtype=np.float64) self.FU[0 * cgdof:1 * cgdof] -= self.p @ self.PU0 self.FU[1 * cgdof:2 * cgdof] -= self.p @ self.PU1 if self.GD == 3: self.FU[2 * cgdof:3 * cgdof] -= self.p @ self.PU2 # 初始应力和等效应力项 self.FU[0 * cgdof:1 * cgdof] -= sigma0 @ self.PU0 self.FU[1 * cgdof:2 * cgdof] -= sigma0 @ self.PU1 if self.GD == 3: self.FU[2 * cgdof:3 * cgdof] -= sigma0 @ self.PU2 # vtk 文件输出 node, cell, cellType, NC = self.mesh.to_vtk() self.points = vtk.vtkPoints() self.points.SetData(vnp.numpy_to_vtk(node)) self.cells = vtk.vtkCellArray() self.cells.SetCells(NC, vnp.numpy_to_vtkIdTypeArray(cell)) self.cellType = cellType
def solve_poisson_2d(self): pde = CosCosData() mesh = pde.init_mesh(n=3, methtype='tri') space = RaviartThomasFiniteElementSpace2d(mesh, p=0)
def __init__(self, mesh, args, ctx): self.ctx = ctx self.args = args # 模拟相关参数 NT = int((args.T1 - args.T0)/args.DT) self.timeline = UniformTimeLine(args.T0, args.T1, NT) self.mesh = mesh if self.ctx.myid == 0: self.GD = mesh.geo_dimension() if self.GD == 2: self.vspace = RaviartThomasFiniteElementSpace2d(self.mesh, p=0) # 速度空间 elif self.GD == 3: self.vspace = RaviartThomasFiniteElementSpace3d(self.mesh, p=0) self.pspace = self.vspace.smspace # 压力和饱和度所属的空间, 分片常数 self.cspace = LagrangeFiniteElementSpace(self.mesh, p=1) # 位移空间 # 上一时刻物理量的值 self.v = self.vspace.function() # 速度函数 self.p = self.pspace.function() # 压力函数 self.s = self.pspace.function() # 水的饱和度函数 默认为0, 初始时刻区域内水的饱和度为0 self.u = self.cspace.function(dim=self.GD) # 位移函数 self.phi = self.pspace.function() # 孔隙度函数, 分片常数 # 当前时刻物理量的值, 用于保存临时计算出的值, 模型中系数的计算由当前时刻 # 的物理量的值决定 self.cv = self.vspace.function() # 速度函数 self.cp = self.pspace.function() # 压力函数 self.cs = self.pspace.function() # 水的饱和度函数 默认为0, 初始时刻区域内水的饱和度为0 self.cu = self.cspace.function(dim=self.GD) # 位移函数 self.cphi = self.pspace.function() # 孔隙度函数, 分片常数 # 初值 self.s[:] = self.mesh.celldata['fluid_0'] self.p[:] = self.mesh.celldata['pressure_0'] # MPa self.phi[:] = self.mesh.celldata['porosity_0'] # 初始孔隙度 self.s[:] = self.mesh.celldata['fluid_0'] self.cp[:] = self.p # 初始地层压力 self.cphi[:] = self.phi # 当前孔隙度系数 # 源汇项 self.f0 = self.cspace.function() self.f1 = self.cspace.function() self.f0[:] = self.mesh.nodedata['source_0'] # 流体 0 的源汇项 self.f1[:] = self.mesh.nodedata['source_1'] # 流体 1 的源汇项 # 一些常数矩阵和向量 # 速度散度矩阵, 速度方程对应的散度矩阵, (\nabla\cdot v, w) self.B = self.vspace.div_matrix() # 压力方程对应的位移散度矩阵, (\nabla\cdot u, w) 位移散度矩阵 # * 注意这里利用了压力空间分片常数, 线性函数导数也是分片常数的事实 c = self.mesh.entity_measure('cell') c *= self.mesh.celldata['biot'] val = self.mesh.grad_lambda() # (NC, TD+1, GD) val *= c[:, None, None] pc2d = self.pspace.cell_to_dof() cc2d = self.cspace.cell_to_dof() pgdof = self.pspace.number_of_global_dofs() cgdof = self.cspace.number_of_global_dofs() I = np.broadcast_to(pc2d, shape=cc2d.shape) J = cc2d self.PU0 = csr_matrix( (val[..., 0].flat, (I.flat, J.flat)), shape=(pgdof, cgdof) ) self.PU1 = csr_matrix( (val[..., 1].flat, (I.flat, J.flat)), shape=(pgdof, cgdof) ) if self.GD == 3: self.PU2 = csr_matrix( (val[..., 2].flat, (I.flat, J.flat)), shape=(pgdof, cgdof) ) # 线弹性矩阵的右端向量 self.FU = np.zeros(self.GD*cgdof, dtype=np.float64) self.FU[0*cgdof:1*cgdof] -= [email protected] self.FU[1*cgdof:2*cgdof] -= [email protected] if self.GD == 3: self.FU[2*cgdof:3*cgdof] -= [email protected] # 初始应力和等效应力项 sigma = self.mesh.celldata['stress_0'] + self.mesh.celldata['stress_eff']# 初始应力和等效应力之和 self.FU[0*cgdof:1*cgdof] -= [email protected] self.FU[1*cgdof:2*cgdof] -= [email protected] if self.GD == 3: self.FU[2*cgdof:3*cgdof] -= [email protected]
from fealpy.solver import SaddlePointFastSolver p = int(sys.argv[1]) # RT 空间的次数 n = int(sys.argv[2]) # 初始网格部分段数 maxit = int(sys.argv[3]) # 迭代求解次数 pde = CosCosData() # pde 模型 box = pde.domain() # 模型区域 mf = MeshFactory() # 网格工场 for i in range(maxit): mesh = mf.boxmesh2d(box, nx=n, ny=n, meshtype='tri') space = RaviartThomasFiniteElementSpace2d(mesh, p=p) udof = space.number_of_global_dofs() pdof = space.smspace.number_of_global_dofs() gdof = udof + pdof print("step ", i, " with number of dofs:", gdof) uh = space.function() ph = space.smspace.function() M = space.mass_matrix() B = -space.div_matrix() F0 = -space.set_neumann_bc(pde.dirichlet) # Poisson 的 D 氏边界变为 Neumann F1 = -space.smspace.source_vector(pde.source)
from fealpy.mesh import TriangleMesh, PolygonMesh, MeshFactory ## space from fealpy.functionspace import RaviartThomasFiniteElementSpace2d from fealpy.functionspace import DivFreeNonConformingVirtualElementSpace2d from fealpy.functionspace import ReducedDivFreeNonConformingVirtualElementSpace2d from fealpy.functionspace import ScaledMonomialSpace2d from fealpy.pde.stokes_model_2d import StokesModelData_0, StokesModelData_1 p = 2 n = 5 tmesh = MeshFactory.boxmesh2d([0, 1, 0, 1], nx=5, ny=5, meshtype='tri') # RT 空间 space0 = RaviartThomasFiniteElementSpace2d(tmesh, p=p - 1) # 三角形转化为多边形网格, 注意这里要求三角形的 0 号边转化后仍然是多边形的 0 # 号边 NC = tmesh.number_of_cells() NV = 3 node = tmesh.entity('node') cell = tmesh.entity('cell')[:, [1, 2, 0]] cellLocation = np.arange(0, (NC + 1) * NV, NV) pmesh = PolygonMesh(node, cell.reshape(-1), cellLocation) # 缩减虚单元空间 space1 = ReducedDivFreeNonConformingVirtualElementSpace2d(pmesh, p=p) b0 = space1.source_vector(pde.source) b1 = space1.pressure_robust_source_vector(pde.source, space0)
def solve_poisson_2d(self, n=3, p=0, plot=True): pde = CosCosData() mesh = pde.init_mesh(n=n, meshtype='tri') space = RaviartThomasFiniteElementSpace2d(mesh, p=p) udof = space.number_of_global_dofs() pdof = space.smspace.number_of_global_dofs() gdof = udof + pdof uh = space.function() ph = space.smspace.function() A = space.stiff_matrix() B = space.div_matrix() F1 = space.source_vector(pde.source) AA = bmat([[A, -B], [-B.T, None]], format='csr') if True: F0 = -space.set_neumann_bc(pde.dirichlet) FF = np.r_['0', F0, F1] x = spsolve(AA, FF).reshape(-1) uh[:] = x[:udof] ph[:] = x[udof:] error0 = space.integralalg.L2_error(pde.flux, uh) def f(bc): xx = mesh.bc_to_point(bc) return (pde.solution(xx) - ph(xx))**2 error1 = space.integralalg.integral(f) print(error0, error1) else: isBdDof = -space.set_dirichlet_bc(uh, pde.neumann) x = np.r_['0', uh, ph] isBdDof = np.r_['0', isBdDof, np.zeros(pdof, dtype=np.bool_)] FF = np.r_['0', np.zeros(udof, dtype=np.float64), F1] FF -= AA @ x bdIdx = np.zeros(gdof, dtype=np.int) bdIdx[isBdDof] = 1 Tbd = spdiags(bdIdx, 0, gdof, gdof) T = spdiags(1 - bdIdx, 0, gdof, gdof) AA = T @ AA @ T + Tbd FF[isBdDof] = x[isBdDof] x[:] = spsolve(AA, FF) uh[:] = x[:udof] ph[:] = x[udof:] error0 = space.integralalg.L2_error(pde.flux, uh) def f(bc): xx = mesh.bc_to_point(bc) return (pde.solution(xx) - ph(xx))**2 error1 = space.integralalg.integral(f) print(error0, error1) if plot: box = [-0.5, 1.5, -0.5, 1.5] fig = plt.figure() axes = fig.gca() mesh.add_plot(axes, box=box) #mesh.find_node(axes, showindex=True) #mesh.find_edge(axes, showindex=True) #mesh.find_cell(axes, showindex=True) node = ps.reshape(-1, 2) uv = uh.reshape(-1, 2) axes.quiver(node[:, 0], node[:, 1], uv[:, 0], uv[:, 1]) plt.show()