Source code for festim.subdomain.volume_subdomain

import types
from collections.abc import Callable

import dolfinx
import numpy as np
from dolfinx import fem
from dolfinx.mesh import Mesh, locate_entities
from numpy import typing as npt
from scifem.mesh import transfer_meshtags_to_submesh

from festim.material import Material

# Define the appropriate method based on the version
try:
    from dolfinx.mesh import EntityMap

    entity_map_type = EntityMap
except ImportError:
    entity_map_type = npt.NDArray[np.int32]


[docs] class VolumeSubdomain: """ Volume subdomain class Args: id: the id of the volume subdomain submesh: the submesh of the volume subdomain cell_map: the cell map of the volume subdomain parent_mesh: the parent mesh of the volume subdomain parent_to_submesh: the parent to submesh map of the volume subdomain v_map: the vertex map of the volume subdomain n_map: the normal map of the volume subdomain facet_to_parent: the facet to parent map of the volume subdomain ft: the facet meshtags of the volume subdomain padded: whether the subdomain is padded (for 0.9 compatibility) u: the solution function of the subdomain u_n: the previous solution function of the subdomain material: the material assigned to the subdomain sub_T: the sub temperature field in the subdomain """ id: int submesh: dolfinx.mesh.Mesh cell_map: "entity_map_type" parent_mesh: dolfinx.mesh.Mesh parent_to_submesh: "entity_map_type" v_map: "entity_map_type" n_map: np.ndarray facet_to_parent: np.ndarray ft: dolfinx.mesh.MeshTags padded: bool # NOTE: Once 0.9 support is dropped, this can be removed u: dolfinx.fem.Function u_n: dolfinx.fem.Function material: Material sub_T: fem.Function | float def __init__( self, id, material, locator: Callable | None = None, name: str | None = None ): self.id = id self.material = material self.locator = locator self.name = name @property def name(self): return self._name @name.setter def name(self, value): if value is None: self._name = None elif isinstance(value, str): self._name = value else: raise TypeError("Name must be a string")
[docs] def create_subdomain(self, mesh: dolfinx.mesh.Mesh, marker: dolfinx.mesh.MeshTags): """ Creates the following attributes: ``.parent_mesh``, ``.submesh``, ``.cell_map``, ``.v_map``, ``padded``, and the entity map ``parent_to_submesh``. Only used in ``festim.HydrogenTransportProblemDiscontinuous`` Args: mesh (dolfinx.mesh.Mesh): the parent mesh marker (dolfinx.mesh.MeshTags): the parent volume markers """ assert marker.dim == mesh.topology.dim self.parent_mesh = ( mesh # NOTE: it doesn't seem like we use this attribute anywhere ) entities = marker.find(self.id) self.submesh, self.cell_map, self.v_map, self.n_map = ( dolfinx.mesh.create_submesh(mesh, marker.dim, entities) ) if isinstance(entity_map_type, types.GenericAlias): num_cells_local = ( mesh.topology.index_map(marker.dim).size_local + mesh.topology.index_map(marker.dim).num_ghosts ) self.parent_to_submesh = np.full(num_cells_local, -1, dtype=np.int32) self.parent_to_submesh[self.cell_map] = np.arange( len(self.cell_map), dtype=np.int32 ) self.padded = False
def transfer_meshtag(self, mesh: dolfinx.mesh.Mesh, tag: dolfinx.mesh.MeshTags): # Transfer meshtags to submesh assert self.submesh is not None, "Need to call create_subdomain first" self.ft, self.facet_to_parent = transfer_meshtags_to_submesh( tag, self.submesh, self.v_map, self.cell_map )
[docs] def locate_subdomain_entities(self, mesh: Mesh) -> npt.NDArray[np.int32]: """Locates all cells in subdomain borders within domain Args: mesh: the mesh of the model Returns: entities: the entities of the subdomain """ if self.locator is None: raise ValueError("No locator function provided for locating cells.") entities = locate_entities(mesh, mesh.topology.dim, self.locator) return entities
[docs] class VolumeSubdomain1D(VolumeSubdomain): """ Volume subdomain class for 1D cases Args: id (int): the id of the volume subdomain borders (list of float): the borders of the volume subdomain material (festim.Material): the material of the volume subdomain Attributes: id (int): the id of the volume subdomain borders (list of float): the borders of the volume subdomain material (festim.Material): the material of the volume subdomain Examples: .. testsetup:: VolumeSubdomain1D from festim import VolumeSubdomain1D, Material my_mat = Material(D_0=1, E_D=1, name="test_mat") .. testcode:: VolumeSubdomain1D VolumeSubdomain1D(id=1, borders=[0, 1], material=my_mat) """ def __init__(self, id, borders, material) -> None: super().__init__( id, material, locator=lambda x: np.logical_and(x[0] >= borders[0], x[0] <= borders[1]), ) self.borders = borders
def find_volume_from_id(id: int, volumes: list): """Returns the correct volume subdomain object from a list of volume ids based on an int Args: id (int): the id of the volume subdomain volumes (list): the list of volumes Returns: festim.VolumeSubdomain: the volume subdomain object with the correct id Raises: ValueError: if the volume name is not found in the list of volumes """ for vol in volumes: if vol.id == id: return vol raise ValueError(f"id {id} not found in list of volumes")