Source code for pygeon.grids.md_grid

"""Module for the MixedDimensionalGrid class."""

from typing import Callable, cast

import numpy as np
import porepy as pp

import pygeon as pg


[docs] class MixedDimensionalGrid(pp.MixedDimensionalGrid): """ Represents a mixed-dimensional grid. This class extends the functionality of the `pp.MixedDimensionalGrid` class. It provides methods for initializing the grid, computing geometry, and tagging mesh entities. """
[docs] def compute_geometry(self) -> None: """ Compute geometric entities and tags for the subdomains and interfaces. This method iterates over the subdomains and interfaces of the grid and computes their geometric entities and tags. It calls the `compute_geometry` method of each subdomain and interface, passing the necessary parameters. Finally, it tags the leaf nodes of the grid. Args: None Returns: None """ for sd in self.subdomains(): sd.compute_geometry() for intf in self.interfaces(): intf = cast(pg.MortarGrid, intf) sd_pair = self.interface_to_subdomain_pair(intf) intf.assign_sd_pair(cast(tuple[pg.Grid, pg.Grid], sd_pair)) intf.compute_geometry() self.tag_leafs()
[docs] def num_subdomain_faces(self, cond: Callable[[pp.Grid], bool] | None = None) -> int: """ Compute the total number of faces of the mixed-dimensional grid. A function can be passed to filter subdomains and/or interfaces. Args: cond: Callable, predicate with a grid as input. Returns: int: The total number of faces of the mixed-dimensional grid. """ if cond is None: cond = lambda _: True return np.sum([sd.num_faces for sd in self.subdomains() if cond(sd)]).astype( int )
[docs] def num_subdomain_ridges( self, cond: Callable[[pg.Grid], bool] | None = None ) -> int: """ Compute the total number of ridges in the mixed-dimensional grid. A function can be passed to filter subdomains and/or interfaces. Args: cond: Callable. A predicate function that takes a grid as input. Returns: int: The total number of ridges in the mixed-dimensional grid. """ if cond is None: cond = lambda _: True return np.sum( [ sd.num_ridges for pp_sd in self.subdomains() if (sd := cast(pg.Grid, pp_sd)) and cond(sd) ] ).astype(int)
[docs] def num_subdomain_peaks(self, cond: Callable[[pg.Grid], bool] | None = None) -> int: """ Compute the total number of peaks in the mixed-dimensional grid. A function can be passed to filter subdomains and/or interfaces. Args: cond: Callable. A predicate function that takes a grid as input. Returns: int: The total number of peaks in the mixed-dimensional grid. """ if cond is None: cond = lambda _: True return np.sum( [ sd.num_peaks for pp_sd in self.subdomains() if (sd := cast(pg.Grid, pp_sd)) and cond(sd) ] ).astype(int)
[docs] def tag_leafs(self) -> None: """ Tag the mesh entities that correspond to a mesh entity of a lower-dimensional grid in a grid bucket. TODO: Use these tags to generate mixed-dimensional inner products. Args: None Returns: None """ for sd in self.subdomains(): sd = cast(pg.Grid, sd) # Tag the faces that correspond to a cell in a codim 1 domain sd.tags["leaf_faces"] = sd.tags["tip_faces"] + sd.tags["fracture_faces"] # Initialize the other tags sd.tags["leaf_ridges"] = np.zeros(sd.num_ridges, dtype=bool) sd.tags["leaf_peaks"] = np.zeros(sd.num_peaks, dtype=bool) for intf in self.interfaces(): intf = cast(pg.MortarGrid, intf) # Tag the ridges that correspond to a cell in a codim 2 domain if intf.dim >= 1: sd_up, sd_down = self.interface_to_subdomain_pair(intf) sd_up.tags["leaf_ridges"] += ( abs(intf.face_ridges) @ sd_down.tags["leaf_faces"] ).astype("bool") for intf in self.interfaces(): intf = cast(pg.MortarGrid, intf) # Tag the peaks that correspond to a codim 3 domain if intf.dim >= 2: sd_up, sd_down = self.interface_to_subdomain_pair(intf) sd_up.tags["leaf_peaks"] += ( abs(intf.ridge_peaks) @ sd_down.tags["leaf_ridges"] ).astype("bool")