Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
    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
Ejemplo n.º 5
0
 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()
Ejemplo n.º 6
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]
Ejemplo n.º 7
0
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')