def solve_poisson_3d(self, n=0, p=0, plot=True): pde = CosCosCosData() mesh = pde.init_mesh(n=n, meshtype='tet') space = RaviartThomasFiniteElementSpace3d(mesh, p=p, q=p + 4) udof = space.number_of_global_dofs() pdof = space.smspace.number_of_global_dofs() gdof = udof + pdof uh = space.function() print('uh:', uh.shape) ph = space.smspace.function() print('ph:', ph.shape) A = space.stiff_matrix() B = space.div_matrix() F1 = space.source_vector(pde.source) AA = bmat([[A, -B], [-B.T, None]], format='csr') F0 = space.neumann_boundary_vector(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)
def basis_coefficients(self, n=0, p=0): pde = X2Y2Z2Data() mesh = pde.init_mesh(n=n, meshtype='tet') space = RaviartThomasFiniteElementSpace3d(mesh, p=p) C = space.basis_coefficients() return C
def __init__(self, vdata, cdata, mesh, timeline, p=0, options={ 'rdir': '/home/why/result', 'step': 1000, 'porosity': 0.2 }): self.options = options self.vdata = vdata self.cdata = cdata self.mesh = mesh self.timeline = timeline self.uspace = RaviartThomasFiniteElementSpace3d(mesh, p=p) self.cspace = ScaledMonomialSpace3d(mesh, p=p + 1) self.uh = self.uspace.function() # 速度场自由度数组 self.ph = self.uspace.smspace.function() # 压力场自由度数组 self.ch = self.cspace.function() # 浓度场自由度数组 # 初始浓度场设为 0 ldof = self.cspace.number_of_local_dofs() print("cell_mass_matrix:") 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, 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 show_basis(self, p=0): mesh = self.meshfactory.one_tetrahedron_mesh(ttype='equ') space = RaviartThomasFiniteElementSpace3d(mesh, p=p, q=2) fig = plt.figure() space.show_basis(fig) plt.show()
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]
m = int(sys.argv[1]) n = int(sys.argv[2]) p = int(sys.argv[3]) if m == 0: pde = CornerData3D() elif m == 1: pass elif m == 2: pass elif m == 3: pass mesh = pde.init_mesh(n=n, meshtype='tet') space = RaviartThomasFiniteElementSpace3d(mesh, p=p) udof = space.number_of_global_dofs() pdof = space.smspace.number_of_global_dofs() gdof = udof + pdof + 1 uh = space.function() ph = space.smspace.function() A = space.stiff_matrix() B = space.div_matrix() C = space.smspace.cell_mass_matrix()[:, 0, :].reshape(-1) F1 = space.source_vector(pde.source) AA = bmat([[A, -B, None], [-B.T, None, C[:, None]], [None, C, None]], format='csr')