Create a piecewise constant field for spatially varying properties#
Objectives
We provide here a utility function to create a piecewise constant field for each region of a domain
Download sources
import numpy as np
import matplotlib.pyplot as plt
from mpi4py import MPI
from dolfinx import mesh, fem
def create_piecewise_constant_field(domain, cell_markers, property_dict, name=None):
"""Create a piecewise constant field with different values per subdomain.
Parameters
----------
domain : Mesh
`dolfinx` mesh object
cell_markers : MeshTag
cell marker MeshTag
property_dict : dict
A dictionary mapping region tags to physical values {tag: value}
Returns
-------
A DG-0 function
"""
V0 = fem.functionspace(domain, ("DG", 0))
k = fem.Function(V0, name=name)
for tag, value in property_dict.items():
cells = cell_markers.find(tag)
k.x.array[cells] = np.full_like(cells, value, dtype=np.float64)
return k
For instance, we first create a square mesh and define a geometric marker marking a square strip of inner radius a and outer radius b:
N = 40
domain = mesh.create_unit_square(
MPI.COMM_WORLD, N, N, cell_type=mesh.CellType.quadrilateral
)
def strip(x, a, b, eps=1e-8):
return np.logical_and(
np.logical_and(np.abs(x[0] - 0.5) <= b + eps, np.abs(x[1] - 0.5) <= b + eps),
np.logical_or(np.abs(x[0] - 0.5) >= a - eps, np.abs(x[1] - 0.5) >= a - eps),
)
We then use the function mark_entities introduced in Marking facets with geometrical functions to mark the corresponding cells and create a piecewise constant field.
tdim = domain.topology.dim
cell_markers = mark_entities(
domain,
tdim,
{
0: lambda x: strip(x, 0, 0.1),
1: lambda x: strip(x, 0.1, 0.2),
2: lambda x: strip(x, 0.2, 0.3),
3: lambda x: strip(x, 0.3, 0.4),
4: lambda x: strip(x, 0.4, 0.5),
},
)
func = create_piecewise_constant_field(
domain, cell_markers, {k: float(k) for k in range(5)}
)