[petsc-users] Jacobian matrix for dual porosity model

Adrian Croucher a.croucher at auckland.ac.nz
Mon Jun 5 20:40:01 CDT 2017


I am about to generalise the geothermal subsurface flow simulator I'm 
working on so that it can simulate dual-porosity systems, and need some 
advice on the best way to to this within the PETSc framework.

1) Dual porosity:

For anyone not familiar with the idea, dual porosity models are a way of 
simulating flow in fractured media. The main flow in the system takes 
place along the fractures, but fluid is also stored in the 'matrix' rock 
between the fractures. The rocks in the fracture and matrix cells 
usually have different properties (e.g. permeability, porosity).

Starting from a conventional single-porosity finite volume model, dual 
porosity effectively adds a one-dimensional sub-model inside each cell 
(or possibly only in some cells), representing storage in the 'matrix' 
rock. The original single-porosity cells now represent the fractures in 
the rock. Their effective volumes are reduced but their connectivity to 
other fracture cells is unchanged. Each one gets an additional 
connection to a matrix cell. However, the matrix cells are usually not 
connected to each other. In the simplest case there is just one matrix 
cell for every fracture cell, though it is often desirable to use two or 
more, to get better representation of the flow in and out of the matrix. 
In that case the higher-level matrix cells form a one-dimensional 
sub-model for each cell.


2) Simple solution method:

The simplest way to implement this approach is just to add in all the 
matrix cells and treat them the same way as the fracture cells. If the 
original number of single-porosity cells was n, and the number of matrix 
cells per fracture cell is m, then the Jacobian for the system is of 
size (m+1) * n. (In practice we are almost always solving for more than 
one variable per cell, e.g. pressure and temperature, so if there are p 
variables per cell, the total Jacobian size is really (m+1) * n * p, but 
if we think of the Jacobian as a block matrix with blocksize p then the 
total number of blocks is still (m+1) * n.)


2) More efficient solution method:

The straight-forward approach is not very efficient, because it doesn't 
take any advantage of the particular sparsity pattern of the Jacobian. 
Because all the matrix rock sub-models are one-dimensional, the Jacobian 
has a block-tridiagonal high-level structure, in which all of the the 
block matrices (of size n) are themselves block-diagonal (with blocksize 
p), except for the upper left one which has the same sparsity pattern as 
the Jacobian for the original single-porosity system.

An efficient way to solve this linear system is described by, among 
others, Zyvoloski et al (2008): 
http://www.sciencedirect.com/science/article/pii/S0309170807001741

The method is detailed on p. 537, equations 1 - 6. What it amounts to is 
taking successive 2-block-by-2-block sub-systems, starting from the 
bottom right, and replacing the upper left sub-matrix in each case by 
its Schur complement (with a similar modification to the right hand side 
vector). Because all the sub-matrices are block diagonal, these can be 
computed quite cheaply (and in parallel, if the sub-matrices are 
distributed appropriately across the processors). When you get back up 
to the top left of the whole matrix, the remaining modified sub-matrix 
of size n can be solved on its own to get the solution in the fracture 
cells. You can then back-substitute to get the solution in the matrix 
rock cells.

In other words, after a relatively inexpensive reduction process, you 
wind up solving a linear system of size n (same as the original 
single-porosity system, and with the same sparsity pattern- only the 
diagonal and RHS are modified) instead of (m+1) * n. This whole process 
is usually a lot faster than solving the whole (m+1) * n sized linear 
system.


3) PETSc implementation

So, how would I implement this approach in the PETSc framework? Because 
the flow equations are non-linear, solving these linear systems happens 
multiple times each time-step as part of a SNES solve.

One way might be to form the whole Jacobian but somehow use a modified 
KSP solve which would implement the reduction process, do a KSP solve on 
the reduced system of size n, and finally back-substitute to find the 
unknowns in the matrix rock cells.

Another way might be to form only the reduced-size Jacobian and the 
other block-diagonal matrices separately, use KSP to solve the reduced 
system but first incorporate the reduction process into the Jacobian 
calculation routine, and somewhere a post-solve step to back-substitute 
for the unknowns in the matrix cells. However currently we are using 
finite differences to compute these Jacobians and it seems to me it 
would be messy to try to do that separately for each of the 
sub-matrices. Doing it the first way above would avoid all that.

Any suggestions for what might be a good approach? or any other ideas 
that could be easier to implement with PETSc but have similar 
efficiency? I didn't see anything currently in PETSc specifically for 
solving block-tridiagonal systems.

Thanks, Adrian

-- 
Dr Adrian Croucher
Senior Research Fellow
Department of Engineering Science
University of Auckland, New Zealand
email: a.croucher at auckland.ac.nz
tel: +64 (0)9 923 4611



More information about the petsc-users mailing list