discretize.SimplexMesh.get_edge_inner_product_deriv#

SimplexMesh.get_edge_inner_product_deriv(model, do_fast=True, invert_model=False, invert_matrix=False)[source]#

Get a function handle to multiply vector with derivative of edge inner product matrix (or its inverse).

Let M(m) be the edge inner product matrix constructed with a set of physical property parameters m (or its inverse). get_edge_inner_product_deriv constructs a function handle

F(u)=uTM(m)m

which accepts any numpy.array u of shape (n_edges,). That is, get_edge_inner_product_deriv constructs a function handle for computing the dot product between a vector u and the derivative of the edge inner product matrix (or its inverse) with respect to the property parameters. When computed, F(u) returns a scipy.sparse.csr_matrix of shape (n_edges, n_param).

The function handle can be created for isotropic, diagonal isotropic and full tensor physical properties; see notes.

Parameters:
modelnumpy.ndarray

Parameters defining the material properties for every cell in the mesh.

Allows for the following cases:

  • (n_cells) numpy.ndarray : Isotropic case. model contains a scalar physical property value for each cell.

  • (n_cells, dim) numpy.ndarray : Diagonal anisotropic case. Columns are ordered np.c_[σ_xx, σ_yy, σ_zz]. This can also a be a 1D array with the same number of total elements in column major order.

  • (n_cells, 3) numpy.ndarray (dim is 2) or (n_cells, 6) numpy.ndarray (dim is 3) : Full tensor properties case. Columns are ordered np.c_[σ_xx, σ_yy, σ_zz, σ_xy, σ_xz, σ_yz] This can also be a 1D array with the same number of total elements in column major order.

invert_modelbool, optional

The inverse of model is used as the physical property.

invert_matrixbool, optional

Returns the function handle for the inverse of the inner product matrix The inverse not implemented for full tensor properties.

do_fastbool, optional

Do a faster implementation (if available).

Returns:
function

The function handle F(u) which accepts a (n_edges) numpy.ndarray u. The function returns a (n_edges, n_params) scipy.sparse.csr_matrix.

Notes

Let M(m) be the edge inner product matrix (or its inverse) for the set of physical property parameters m. And let u be a discrete quantity that lives on the edges. get_edge_inner_product_deriv creates a function handle for computing the following:

F(u)=uTM(m)m

The dimensions of the sparse matrix constructed by computing F(u) for some u depends on the constitutive relation defined for each cell. These cases are summarized below.

Isotropic Case: The physical property for each cell is defined by a scalar value. Therefore m is a (n_cells) numpy.ndarray. The sparse matrix output by computing F(u) has shape (n_edges, n_cells).

Diagonal Anisotropic Case: In this case, the physical properties for each cell are defined by a diagonal tensor

Σ=[σxx000σyy000σzz]

Thus there are dim * n_cells physical property parameters and m is a (dim * n_cells) numpy.ndarray. The sparse matrix output by computing F(u) has shape (n_edges, dim * n_cells).

Full Tensor Case: In this case, the physical properties for each cell are defined by a full tensor

Σ=[σxxσxyσxzσxyσyyσyzσxzσyzσzz]

Thus there are 6 * n_cells physical property parameters in 3 dimensions, or 3 * n_cells physical property parameters in 2 dimensions, and m is a (n_params) numpy.ndarray. The sparse matrix output by computing F(u) has shape (n_edges, n_params).

Examples

Here, we construct a 4 cell by 4 cell tensor mesh. For our first example we consider isotropic physical properties; that is, the physical properties of each cell are defined a scalar value. We construct the edge inner product matrix and visualize it with a spy plot. We then use get_edge_inner_product_deriv to construct the function handle F(u) and plot the evaluation of this function on a spy plot.

>>> from discretize import TensorMesh
>>> import matplotlib.pyplot as plt
>>> import numpy as np
>>> import matplotlib as mpl
>>> mpl.rcParams.update({'font.size': 14})
>>> rng = np.random.default_rng(45)
>>> mesh = TensorMesh([[(1, 4)], [(1, 4)]])

Next we create a random isotropic model vector, and a random vector to multiply the derivative with (for illustration purposes).

>>> m = rng.random(mesh.nC)  # physical property parameters
>>> u = rng.random(mesh.nF)  # vector of shape (n_edges)
>>> Me = mesh.get_edge_inner_product(m)
>>> F = mesh.get_edge_inner_product_deriv(m)  # Function handle
>>> dFdm_u = F(u)

Plot inner product matrix and its derivative matrix

>>> fig = plt.figure(figsize=(15, 5))
>>> ax1 = fig.add_axes([0.05, 0.05, 0.3, 0.8])
>>> ax1.spy(Me, ms=6)
>>> ax1.set_title("Edge Inner Product Matrix (Isotropic)", fontsize=14, pad=5)
>>> ax1.set_xlabel("Edge Index", fontsize=12)
>>> ax1.set_ylabel("Edge Index", fontsize=12)
>>> ax2 = fig.add_axes([0.43, 0.05, 0.17, 0.8])
>>> ax2.spy(dFdm_u, ms=6)
>>> ax2.set_title(
...     r"$u^T \, \dfrac{\partial M(m)}{\partial m}$ (Isotropic)",
...     fontsize=14, pad=5
... )
>>> ax2.set_xlabel("Parameter Index", fontsize=12)
>>> ax2.set_ylabel("Edge Index", fontsize=12)
>>> plt.show()

(Source code, png, pdf)

../../_images/discretize-SimplexMesh-get_edge_inner_product_deriv-1_00_00.png

For our second example, the physical properties on the mesh are fully anisotropic; that is, the physical properties of each cell are defined by a tensor with parameters σ1, σ2 and σ3. Once again we construct the edge inner product matrix and visualize it with a spy plot. We then use get_edge_inner_product_deriv to construct the function handle F(u) and plot the evaluation of this function on a spy plot.

>>> m = rng.random((mesh.nC, 3))  # physical property parameters
>>> u = rng.random(mesh.nF)     # vector of shape (n_edges)
>>> Me = mesh.get_edge_inner_product(m)
>>> F = mesh.get_edge_inner_product_deriv(m)  # Function handle
>>> dFdm_u = F(u)

Plot the anisotropic inner product matrix and its derivative matrix

>>> fig = plt.figure(figsize=(15, 5))
>>> ax1 = fig.add_axes([0.05, 0.05, 0.3, 0.8])
>>> ax1.spy(Me, ms=6)
>>> ax1.set_title("Edge Inner Product (Full Tensor)", fontsize=14, pad=5)
>>> ax1.set_xlabel("Edge Index", fontsize=12)
>>> ax1.set_ylabel("Edge Index", fontsize=12)
>>> ax2 = fig.add_axes([0.4, 0.05, 0.45, 0.8])
>>> ax2.spy(dFdm_u, ms=6)
>>> ax2.set_title(
...     r"$u^T \, \dfrac{\partial M(m)}{\partial m} \;$ (Full Tensor)",
...     fontsize=14, pad=5
... )
>>> ax2.set_xlabel("Parameter Index", fontsize=12)
>>> ax2.set_ylabel("Edge Index", fontsize=12)
>>> plt.show()

(png, pdf)

../../_images/discretize-SimplexMesh-get_edge_inner_product_deriv-1_01_00.png