Inner Products#

By using the weak formulation of many of the PDEs in geophysical applications, we can rapidly develop discretizations. Much of this work, however, needs a good understanding of how to approximate inner products on our discretized meshes. We will define the inner product as:

(a,b)=Ωabv

where a and b are either scalars or vectors.

Note

The InnerProducts class is a base class providing inner product matrices for meshes and cannot run on its own.

Example problem for DC resistivity#

We will start with the formulation of the Direct Current (DC) resistivity problem in geophysics.

1σj=ϕj=q

In the following discretization, σ and ϕ will be discretized on the cell-centers and the flux, j, will be on the faces. We will use the weak formulation to discretize the DC resistivity equation.

We can define in weak form by integrating with a general face function f:

Ωσ1jf=Ωϕf

Here we can integrate the right side by parts,

(ϕf)=ϕf+ϕf

and rearrange it, and apply the Divergence theorem.

Ωσ1jf=Ω(ϕf)+Ωϕfn

We can then discretize for every cell:

vcellσ1(JxFx+JyFy+JzFz)=ϕvcellDcellF+BC

Note

We have discretized the dot product above, but remember that we do not really have a single vector J, but approximations of j on each face of our cell. In 2D that means 2 approximations of Jx and 2 approximations of Jy. In 3D we also have 2 approximations of Jz.

Regardless of how we choose to approximate this dot product, we can represent this in vector form (again this is for every cell), and will generalize for the case of anisotropic (tensor) sigma.

Fc(vcellΣ1vcell)Jc=ϕvcellDcellF)+BC

We multiply by square-root of volume on each side of the tensor conductivity to keep symmetry in the system. Here Jc is the Cartesian J (on the faces that we choose to use in our approximation) and must be calculated differently depending on the mesh:

Jc=Q(i)JTENSORJc=N(i)1Q(i)JCurv

Here the i index refers to where we choose to approximate this integral, as discussed in the note above. We will approximate this integral by taking the fluxes clustered around every node of the cell, there are 8 combinations in 3D, and 4 in 2D. We will use a projection matrix Q(i) to pick the appropriate fluxes. So, now that we have 8 approximations of this integral, we will just take the average. For the TensorMesh, this looks like:

F18(i=18Q(i)vcellΣ1vcellQ(i))J=FDcellvcellϕ+BC

Or, when generalizing to the entire mesh and dropping our general face function:

MΣ1fJ=Ddiag(v)ϕ+BC

By defining the faceInnerProduct (8 combinations of fluxes in 3D, 4 in 2D, 2 in 1D) to be:

MΣ1f=i=12dP(i)Σ1P(i)

Where d is the dimension of the mesh. The Mf is returned when given the input of Σ1.

Here each P  R(dnC,nF) is a combination of the projection, volume, and any normalization to Cartesian coordinates (where the dot product is well defined):

P(i)=12dIddiag(v)N(i)1Curv onlyQ(i)

Note

This is actually completed for each cell in the mesh at the same time, and the full matrices are returned.

If returnP=True is requested in any of these methods the projection matrices are returned as a list ordered by nodes around which the fluxes were approximated:

# In 3D
P = [P000, P100, P010, P110, P001, P101, P011, P111]
# In 2D
P = [P00, P10, P01, P11]
# In 1D
P = [P0, P1]

The derivation for edgeInnerProducts is exactly the same, however, when we approximate the integral using the fields around each node, the projection matrices look a bit different because we have 12 edges in 3D instead of just 6 faces. The interface to the code is exactly the same.

Defining Tensor Properties#

For 3D:

Depending on the number of columns (either 1, 3, or 6) of mu, the material property is interpreted as follows:

μ=[μ1000μ1000μ1]μ=[μ1000μ2000μ3]μ=[μ1μ4μ5μ4μ2μ6μ5μ6μ3]

For 2D:

Depending on the number of columns (either 1, 2, or 3) of mu, the material property is interpreted as follows:

μ=[μ100μ1]μ=[μ100μ2]μ=[μ1μ3μ3μ2]

Structure of Matrices#

Both the isotropic, and anisotropic material properties result in a diagonal mass matrix. Which is nice and easy to invert if necessary, however, in the fully anisotropic case which is not aligned with the grid, the matrix is not diagonal. This can be seen for a 3D mesh in the figure below.

import discretize
import numpy as np
import matplotlib.pyplot as plt
mesh = discretize.TensorMesh([10,50,3])
m1 = np.random.rand(mesh.nC)
m2 = np.random.rand(mesh.nC,3)
m3 = np.random.rand(mesh.nC,6)
M = list(range(3))
M[0] = mesh.get_face_inner_product(m1)
M[1] = mesh.get_face_inner_product(m2)
M[2] = mesh.get_face_inner_product(m3)
plt.figure(figsize=(13,5))
for i, lab in enumerate(['Isotropic','Anisotropic','Tensor']):
    plt.subplot(131 + i)
    plt.spy(M[i],ms=0.5,color='k')
    plt.tick_params(axis='both',which='both',labeltop='off',labelleft='off')
    plt.title(lab + ' Material Property')
plt.show()

(Source code, png, pdf)

../_images/inner_products-1.png

Taking Derivatives#

We will take the derivative of the fully anisotropic tensor for a 3D mesh, the other cases are easier and will not be discussed here. Let us start with one part of the sum which makes up MΣf and take the derivative when this is multiplied by some vector v:

PΣPv

Here we will let Pv=y and y will have the form:

y=Pv=[y1y2y3]
PΣy=P[σ1σ4σ5σ4σ2σ6σ5σ6σ3][y1y2y3]=P[σ1y1+σ4y2+σ5y3σ4y1+σ2y2+σ6y3σ5y1+σ6y2+σ3y3]

Now it is easy to take the derivative with respect to any one of the parameters, for example, σ1

σ1(PΣy)=P[diag(y1)00]

Whereas σ4, for example, is:

σ4(PΣy)=P[diag(y2)diag(y1)0]

These are computed for each of the 8 projections, horizontally concatenated, and returned.