pmmoto.core package
Initialize the core subpackage and import core modules for PMMoTo.
This package provides core domain, subdomain, and utility functionality.
Submodules
pmmoto.core.boundary_types module
boundary_types.py
Possible boundary types for PMMoTo
- pmmoto.core.boundary_types.boundary_order(boundaries: list[BoundaryType]) BoundaryType
Prove the boundary type for joining boundaries.
Fro edges and corners in 3D, this specifies the boundary type for the feature. #TODO Get rid of this and allow edges and corners to carry all types.
- Parameters:
boundaries (list[BoundaryType]) – boundaries at given feature
- Returns:
The one boundary type for the feature
- Return type:
pmmoto.core.communication module
communication.py
- pmmoto.core.communication.all_gather(data: Any) list[Any]
Gather data from all processes and return the combined result.
- Parameters:
data – Data to be gathered from each process.
- Returns:
List containing data from all processes.
- pmmoto.core.communication.all_reduce(data: Any, op: str | Op = 'sum') Any
Reduce data from all processes using given operation and distribute result.
- Parameters:
data – Local data to reduce (e.g., int, float, NumPy array).
op – MPI operation or string alias (e.g., ‘sum’, ‘max’).
- Returns:
The reduced result, available to all processes.
- Raises:
ValueError – If the provided operation is not supported.
- pmmoto.core.communication.communicate_features(subdomain: Subdomain | PaddedSubdomain | VerletSubdomain, send_data: dict[tuple[int, ...], Any]) dict[tuple[int, ...], Any]
Send data between processes for faces, edges, and corners.
This also swaps the feature ids.
- Parameters:
subdomain (object) – Subdomain object containing rank and features information.
send_data (dict) – The data to be sent to neighboring processes.
- Returns:
- Received data from neighboring processes.
If unpack is True, returns unpacked received data.
- Return type:
dict
- pmmoto.core.communication.gather(data: T, root: int = 0) list[T] | None
Gather data from all processes to the root process.
- Parameters:
data – Data to be gathered from each process.
root – Rank of the root process that receives the data.
- Returns:
List of data on root process, None on others.
- pmmoto.core.communication.update_buffer(subdomain: Subdomain | PaddedSubdomain | VerletSubdomain, img: ndarray[Any, dtype[T]]) ndarray[Any, dtype[T]]
Update the buffer on subdomains based on their current feature info.
- Parameters:
subdomain – The subdomain object.
img – The grid data to be updated.
- Returns:
The updated grid.
pmmoto.core.domain module
domain.py
Defines the Domain class for representing the physical simulation domain in PMMoTo.
- class pmmoto.core.domain.Domain(box: tuple[tuple[float, float], ...], boundary_types: tuple[tuple[BoundaryType, BoundaryType], ...] = ((BoundaryType.END, BoundaryType.END), (BoundaryType.END, BoundaryType.END), (BoundaryType.END, BoundaryType.END)), inlet: tuple[tuple[bool, bool], ...] = ((False, False), (False, False), (False, False)), outlet: tuple[tuple[int, int], ...] = ((False, False), (False, False), (False, False)))
Bases:
object
Represent a physical simulation domain.
- box
Physical bounds for each dimension.
- Type:
tuple[tuple[float, float], …]
- boundary_types
Boundary types for each face. END: No assumption made WALL: Wall boundary condition PERIODIC: Periodic boundary condition (opposing face must also be 2)
- Type:
tuple[tuple[BoundaryType, BoundaryType], …]
- inlet
Inlet flags (must be 0 boundary type).
- Type:
tuple[tuple[bool, bool], …]
- outlet
Outlet flags (must be 0 boundary type).
- Type:
tuple[tuple[bool, bool], …]
- dims
Number of spatial dimensions (default 3).
- Type:
int
- volume
Volume of the domain.
- Type:
float
- periodic
True if any boundary is periodic.
- Type:
bool
- length
Length of the domain in each dimension.
- Type:
tuple[float, …]
Initialize a Domain.
- Parameters:
box (tuple[tuple[float, float], ...]) – Physical bounds for each dimension.
boundary_types (tuple[tuple[int, int], ...], optional) – Boundary types.
inlet (tuple[tuple[int, int], ...], optional) – Inlet flags for each face.
outlet (tuple[tuple[int, int], ...], optional) – Outlet flags for each face.
- get_length() tuple[float, ...]
Calculate the length of the domain in each dimension.
- Returns:
Length in each dimension.
- Return type:
tuple[float, …]
- get_origin() tuple[float, ...]
Determine the domain origin from box.
- Returns:
Domain origin.
- Return type:
tuple[float, …]
- get_volume() floating[Any]
Calculate the volume of the domain.
- Returns:
Volume of the domain.
- Return type:
float
- periodic_check() bool
Check if any external boundary is a periodic boundary.
- Returns:
True if any boundary is periodic, False otherwise.
- Return type:
bool
pmmoto.core.domain_decompose module
decomposed_domain.py
Defines the DecomposedDomain class for dividing a discretized domain into subdomains.
- class pmmoto.core.domain_decompose.DecomposedDomain(subdomains: tuple[int, ...] = (1, 1, 1), **kwargs: Any)
Bases:
DiscretizedDomain
Collection of subdomains for domain decomposition.
Used to divide the domain into subdomains and pass properties to each subdomain.
Initialize a DecomposedDomain.
- Parameters:
subdomains (tuple[int, int, int] optional) – Number of subdomains
**kwargs – Additional arguments passed to DiscretizedDomain.
- classmethod from_discretized_domain(discretized_domain: DiscretizedDomain, subdomains: tuple[int, ...]) Self
Create a DecomposedDomain from an existing DiscretizedDomain and subdomains.
- Parameters:
discretized_domain (DiscretizedDomain) – The discretized domain object.
subdomains – Number of subdomains in each spatial dimension.
- Returns:
New decomposed domain instance.
- Return type:
- gen_map() ndarray[Any, dtype[int64]]
Generate process lookup map for subdomains.
- Map values:
-2: Wall Boundary Condition -1: No Assumption Boundary Condition >=0: proc_ID
- Returns:
Map array with process IDs and boundary flags.
- Return type:
np.ndarray
- get_neighbor_ranks(sd_index: tuple[int, ...]) dict[tuple[int, ...], int]
Determine the neighbor process rank for each feature.
- Parameters:
sd_index (tuple[int, int, int]) – Index of the subdomain.
- Returns:
Mapping from feature index to neighbor rank.
- Return type:
dict
pmmoto.core.domain_discretization module
domain_discretization.py
Defines the DiscretizedDomain class for discretizing a physical domain into voxels.
- class pmmoto.core.domain_discretization.DiscretizedDomain(voxels: tuple[int, ...] = (1, 1, 1), **kwargs: Any)
Bases:
Domain
Discretize a physical domain into a voxel grid.
This class extends the base Domain class to include voxelization and calculation of voxel resolution and coordinates.
Initialize a discretized domain.
- Parameters:
voxels (tuple[int, int, int], optional) – Number of voxels in each dimension.
**kwargs – Additional arguments passed to the base Domain class.
- classmethod from_domain(domain: Domain, voxels: tuple[int, ...]) Self
Create a DiscretizedDomain from an existing Domain and voxel counts.
- Parameters:
domain (Domain) – The base domain object.
voxels (tuple[int, int, int]) – Number of voxels in each dimension.
- Returns:
New discretized domain instance.
- Return type:
- static get_coords(box: tuple[tuple[float, float], ...], voxels: tuple[int, ...], resolution: tuple[float, ...]) list[ndarray[Any, dtype[float64]]]
Determine the physical locations of voxel centroids.
- Parameters:
box (tuple[tuple[float, float], ...]) – Physical bounds for each dimension.
voxels (tuple[int,int, int]) – Number of voxels in each dimension.
resolution (tuple[float, float, float]) – Voxel size in each dimension.
- Returns:
List of arrays with centroid coordinates.
- Return type:
list[np.ndarray]
- get_resolution() tuple[float, ...]
Calculate the physical size of each voxel in every dimension.
- Returns:
tuple[float, float, float] Resolution (voxel size) in each dimension.
pmmoto.core.features module
features.py
This holds features of a cube: faces edges, and corners
- class pmmoto.core.features.Corner(feature_id: tuple[int, ...], neighbor_rank: int, boundary_type: BoundaryType, global_boundary: bool | None = None)
Bases:
Feature
Corner information for a subdomain.
Need to distinguish between internal and external corners. There are 8 external corners. All others are termed internal.
Initialize a Corner feature.
- Parameters:
feature_id – Feature identifier (tuple).
neighbor_rank – Neighboring process rank.
boundary_type – Boundary type.
global_boundary – Whether this is a global boundary (bool).
- get_periodic_correction() tuple[int, ...]
Determine spatial correction factor (shift) if periodic
- class pmmoto.core.features.Edge(feature_id: tuple[int, ...], neighbor_rank: int, boundary_type: BoundaryType, global_boundary: bool | None = None)
Bases:
Feature
Edge information for a subdomain.
Need to distinguish between internal and external edges. There are 12 external corners. All others are termed internal.
Initialize an Edge feature.
- Parameters:
feature_id – Feature identifier (tuple).
neighbor_rank – Neighboring process rank.
boundary_type – Boundary type.
global_boundary – Whether this is a global boundary (bool).
- get_periodic_correction() tuple[int, ...]
Determine spatial correction factor if periodic
- class pmmoto.core.features.Face(feature_id: tuple[int, ...], neighbor_rank: int, boundary_type: BoundaryType, global_boundary: bool | None = None, inlet: bool | None = None, outlet: bool | None = None)
Bases:
Feature
Face information for a subdomain.
Initialize a Face feature.
- Parameters:
feature_id – Feature identifier (tuple).
neighbor_rank – Neighboring process rank.
boundary_type – Boundary type.
global_boundary – Whether this is a global boundary (bool).
inlet – Whether this face is an inlet (bool).
outlet – Whether this face is an outlet (bool).
- get_direction() bool
Determine if the face is point in the forward direction.
-1 for the non-negative feature id
- Returns:
_description_
- Return type:
_type_
- get_periodic_correction() tuple[int, ...]
Determine spatial correction factor if periodic.
- Returns:
A tuple of correction values for each spatial dimension.
- get_slice() tuple[int | slice, ...]
Extract a 2D slice index for accessing a boundary face in a 3D array.
The method inspects self.feature_id, which defines the orientation of a face in 3D space. It returns a tuple with one fixed index (either 0 or -1) to select a specific boundary face, and slice(None) for the remaining dimensions.
- Returns:
A 3-element tuple used to index a 2D face from a 3D array.
- Return type:
Tuple[int | slice, … ]
- get_strides(strides: tuple[int, ...]) int
Return the stride corresponding to the active dimension in the feature ID.
This method is used to identify which stride (among the three dimensions) is relevant based on the nonzero entry in self.feature_id.
- Parameters:
strides (Tuple[int, int, int]) – A 3-element tuple representing the strides of a NumPy array, typically from .strides.
- Returns:
The stride value corresponding to the active axis.
- Return type:
int
- map_to_index() int
Return the 1d-index for face.
- class pmmoto.core.features.Feature(dim: int, feature_id: tuple[int, ...], neighbor_rank: int, boundary_type: BoundaryType, global_boundary: bool | None = None)
Bases:
object
Base class for holding feature: {face, edge, corner} information.
This is the main abstraction for handling boundary conditions and parallel communication.
Initialize a Feature.
- Parameters:
dim – dimension
feature_id – Feature identifier (tuple).
neighbor_rank – Neighboring process rank.
boundary_type – Boundary type (e.g., “wall”, “periodic”).
global_boundary – Whether this is a global boundary (bool).
- compute_lower_face(lower_pad: int) list[int]
Determine lower face voxels
- compute_lower_neighbor(lower_pad: int) list[int]
Determine lower neighbor face voxels
- compute_upper_face(length: int, upper_pad: int) list[int]
Determine upper face voxels
- compute_upper_neighbor(length: int, upper_pad: int) list[int]
Determine upper neighbor face voxels
- convert_feature_id(index: tuple[int, ...] | None = None) int
Convert the feature type to id.
- Returns:
feature id
- Return type:
int
- get_voxels(voxels: tuple[int, ...], pad: tuple[tuple[int, int], ...] = ((0, 0), (0, 0), (0, 0))) None
Determine the voxel indices for the feature
- is_periodic(boundary_type: BoundaryType) bool
Determine if a feature is periodic
- Returns:
True if periodic
- Return type:
bool
pmmoto.core.logging module
logging.py
Setup of the logger
- class pmmoto.core.logging.MPIFormatter(*args: Any, **kwargs: Any)
Bases:
Formatter
Custom formatter that includes MPI rank
Initialize the formatter with specified format strings.
Initialize the formatter either with the specified format string, or a default as described above. Allow for specialized date formatting with the optional datefmt argument. If datefmt is omitted, you get an ISO8601-like (or RFC 3339-like) format.
Use a style parameter of ‘%’, ‘{’ or ‘$’ to specify that you want to use one of %-formatting,
str.format()
({}
) formatting orstring.Template
formatting in your format string.Changed in version 3.2: Added the
style
parameter.- format(record: LogRecord) str
Add mpi information
- pmmoto.core.logging.get_logger() Logger
Get or create the logger instance
- pmmoto.core.logging.setup_logger(name: str = 'pmmoto', log_dir: str = 'logs') Logger
Configure logging for both serial and parallel runs
- Parameters:
name – Logger name (default: “pmmoto”)
log_dir – Directory to store log files (default: “logs”)
- Returns:
Configured logger instance
- Return type:
logging.Logger
pmmoto.core.orientation module
orientation.py
Defines orientation and feature indexing utilities for PMMoTo subdomains.
- pmmoto.core.orientation.get_boundary_id(boundary_index: tuple[int, ...]) int
Determine boundary ID from a boundary index.
- Parameters:
boundary_index (list[int] or tuple[int]) – Boundary index for [x, y, z],
-1 (values)
0
1.
- Returns:
Encoded boundary ID.
- Return type:
int
pmmoto.core.pmmoto module
pmmoto.py
- pmmoto.core.pmmoto.initialize(voxels: tuple[int, ...], box: tuple[tuple[float, float], ...] = ((0, 1.0), (0, 1.0), (0, 1)), subdomains: tuple[int, ...] = (1, 1, 1), boundary_types: tuple[tuple[BoundaryType, BoundaryType], ...] = ((BoundaryType.END, BoundaryType.END), (BoundaryType.END, BoundaryType.END), (BoundaryType.END, BoundaryType.END)), inlet: tuple[tuple[bool, bool], ...] = ((False, False), (False, False), (False, False)), outlet: tuple[tuple[bool, bool], ...] = ((False, False), (False, False), (False, False)), reservoir_voxels: int = 0, rank: int = 0, pad: tuple[int, ...] = (1, 1, 1), verlet_domains: tuple[int, ...] = (1, 1, 1), return_subdomain: bool = False) Subdomain | PaddedSubdomain | VerletSubdomain
Initialize PMMoTo domain and subdomain classes and check for valid inputs.
pmmoto.core.subdomain module
subdomains.py
Defines the Subdomain class for domain decomposition and parallelization in PMMoTo.
- class pmmoto.core.subdomain.Subdomain(rank: int, decomposed_domain: DecomposedDomain)
Bases:
DiscretizedDomain
Decompose the domain into subdomains for parallelization.
Initialize a Subdomain.
- Parameters:
rank (int) – Rank of the subdomain.
decomposed_domain – Decomposed domain object.
- check_boundary_type(type: BoundaryType) bool
Determine if boundary type on subdomain.
- get_boundary_types() tuple[tuple[BoundaryType, BoundaryType], ...]
Determine the boundary type for each subdomain.
- Returns:
Tuple specifying boundary type for each face
- Return type:
tuple[tuple[str,str],…]
- get_box(voxels: tuple[int, ...]) tuple[tuple[float, float], ...]
Determine the bounding box for each subdomain.
Note
Subdomains are divided such that voxel spacing is constant.
- Parameters:
voxels (tuple) – Number of voxels in each dimension.
- Returns:
Bounding box for each dimension.
- Return type:
tuple
- get_centroid() ndarray[Any, dtype[float64]]
Determine the centroid of a subdomain.
- Returns:
Centroid coordinates.
- Return type:
np.ndarray
- get_global_boundary() tuple[tuple[bool, bool], ...]
Determine if the subdomain is on the domain boundary.
For a subdomain to be on a domain boundary, the subdomain index must contain either 0 or the number of subdomains.
- Returns:
Tuple of bools whether face is on boundary
- Return type:
tuple[tuple[bool,bool],…]
- get_img_index(coordinates: tuple[float, ...]) tuple[int, ...] | None
Given coordinates, return the corresponding index in the img array.
- Parameters:
coordinates (tuple[float, float, float]) – The (x, y, z) coordinates.
- Returns:
The (i, j, k) index in the img array, or None if out of bounds.
- Return type:
tuple[int, int, int] or None
- static get_index(rank: int, subdomains: tuple[int, ...]) tuple[int, ...]
Determine the index of the subdomain in the decomposition.
- Parameters:
rank (int) – The rank of the subdomain.
subdomains (tuple[int, int, int]) – Number of subdomains in each dimension.
- Returns:
Index of the subdomain in the decomposition grid.
- Return type:
tuple[int, int, int]
- get_inlet() tuple[tuple[bool, bool], ...]
Determine if the subdomain lies on the inlet boundaries.
A subdomain is on an inlet if: - It is at the edge of the global domain (index is 0 or max in a dimension). - The corresponding global boundary type is 0 (denoting an inlet).
- Returns:
bool if subdomain face is on inlet.
- Return type:
tuple[tuple[bool, bool], …]
- get_length() tuple[float, ...]
Calculate the length of the subdomain in each dimension.
- Returns:
Length in each dimension.
- Return type:
tuple[float, …]
- get_origin() tuple[float, ...]
Determine the domain origin from box.
- Returns:
Domain origin.
- Return type:
tuple[float, …]
- get_outlet() tuple[tuple[bool, bool], ...]
Determine if the subdomain lies on the inlet boundaries.
A subdomain is on an outlet if: - It is at the edge of the global domain (index is 0 or max in a dimension). - The corresponding global boundary type is 0 (denoting an outlet).
- Returns:
bool if subdomain face is on outlet.
- Return type:
tuple[tuple[bool, bool], …]
- get_own_voxels() ndarray[Any, dtype[integer[Any]]]
Determine the index for the voxels owned by this subdomain.
- Returns:
Array of indices for owned voxels.
- Return type:
np.ndarray
- get_radius() Any
Determine the radius of a subdomain.
- Returns:
Radius of the subdomain.
- Return type:
float
- static get_start(index: tuple[int, ...], domain_voxels: tuple[float, ...], subdomains: tuple[int, ...]) tuple[int, ...]
Determine the start of the subdomain.
- Parameters:
index (tuple[int, int, int]) – Subdomain index.
domain_voxels (tuple[float, float, float]) – Number of voxels per dimension
subdomains (tuple[int, int, int]) – Number of subdomains per dimension.
- Returns:
Start voxel indices - minimum voxel ID.
- Return type:
tuple[int, int, int]
- static get_voxels(index: tuple[int, ...], domain_voxels: tuple[int, ...], subdomains: tuple[int, ...]) tuple[int, ...]
Calculate number of voxels in each subdomain.
- Parameters:
index (tuple) – Index of the subdomain.
domain_voxels (tuple) – Number of voxels in the full domain.
subdomains (tuple) – Number of subdomains in each dimension.
- Returns:
tuple[int, int, int] Number of voxels in each dimension for this subdomain.
- periodic_check() bool
Determine if subdomain is periodic
Returns: bool if and feature is periodic
- set_wall_bcs(img: ndarray[Any, dtype[T]]) ndarray[Any, dtype[T]]
Force solid on external boundaries if wall boundary conditions are specified.
- Parameters:
img (np.ndarray) – Image array to update.
- Returns:
Updated image array with wall boundaries set to solid.
- Return type:
np.ndarray
pmmoto.core.subdomain_features module
subdomain_features.py
Defines feature classes and utilities for handling subdomain faces, edges, and corners, including boundary and periodicity information.
- class pmmoto.core.subdomain_features.SubdomainFeatures(subdomain: Subdomain | PaddedSubdomain, voxels: tuple[int, ...], pad: tuple[tuple[int, int], ...] = ((0, 0), (0, 0), (0, 0)))
Bases:
object
Container for all features (faces, edges, corners) of a subdomain.
- property all_features: Iterator[tuple[tuple[int, ...], Face | Edge | Corner]]
Iterates through features
- collect_features() None
Collect information for faces, edges, and corners for a subdomain.
- collect_periodic_corrections() dict[tuple[int, ...], tuple[int, ...]]
Collect periodic correction vectors for all periodic features.
- Parameters:
features (dict) – Dictionary with keys “faces”, “edges”, “corners”.
- Returns:
Mapping from feature_id to periodic correction tuple.
- Return type:
dict
- collect_periodic_features() list[tuple[int, ...]]
Collect all periodic features from a features dictionary.
- Returns:
List of feature_ids that are periodic.
- Return type:
list
- get_boundary_type(feature_id: tuple[int, ...], neighbor_rank: int) BoundaryType
Determine the boundary type for a feature.
For a feature to be on a domain boundary, the subdomain index must contain either 0 or the number of subdomains.
- Returns:
If feature is on domain boundary
- Return type:
bool
- get_feature_member(feature_id: tuple[int, ...], member_name: str) Any
Get the value of a member from the Face, Edge, or Corner with feature_id.
- Parameters:
feature_id (tuple[int, ...]) – The feature ID.
member_name (str) – Name of the member to retrieve.
- Returns:
Value of the requested member.
- Return type:
Any
- Raises:
KeyError – If feature_id is not found.
AttributeError – If member_name does not exist.
- get_global_boundary(feature_id: tuple[int, ...]) bool
Determine if a feature is on the domain boundary.
For a feature to be on a domain boundary, the subdomain index must contain either 0 or the number of subdomains.
- Returns:
If feature is on domain boundary
- Return type:
bool
- set_feature_voxels(voxels: tuple[int, ...]) None
Set the own and neighbor voxels for each feature
pmmoto.core.subdomain_padded module
subdomain_padded.py
Defines the PaddedSubdomain class for handling subdomains with padding, facilitating parallel algorithms in PMMoTo.
- class pmmoto.core.subdomain_padded.PaddedSubdomain(rank: int, decomposed_domain: DecomposedDomain, pad: tuple[int, ...] = (0, 0, 0), reservoir_voxels: int = 0)
Bases:
Subdomain
Padded subdomain to facilitate development of parallel algorithms.
Initialize a PaddedSubdomain.
- Parameters:
rank (int) – Rank of the subdomain.
decomposed_domain – Decomposed domain object.
pad (tuple[int, int, int], optional) – Padding for each dimension.
reservoir_voxels (int, optional) – Reservoir voxels to pad at inlet/outlet.
- extend_padding(pad: tuple[int, ...]) tuple[tuple[tuple[int, int], ...], SubdomainFeatures]
Extend pad to boundaries of subdomain.
Padding is applied to all boundaries except ‘end’ and ‘wall’ boundary types, where pad is limited to 1. Padding must be equal on opposite features.
- Parameters:
pad (tuple[int, ...]) – Pad length for each dimension.
- Returns:
(pad, extended_features)
- Return type:
tuple
- get_own_voxels() ndarray[Any, dtype[int64]]
Determine the index for the voxels owned by this subdomain.
- Returns:
Array of indices for owned voxels.
- Return type:
np.ndarray
- get_padded_box() tuple[tuple[float, float], ...]
Determine the bounding box for each subdomain.
Note
Subdomains are divided such that voxel spacing is constant.
- Returns:
Bounding box for each dimension.
- Return type:
tuple
- static get_padded_start(index: tuple[int, ...], domain_voxels: tuple[int, ...], subdomains: tuple[int, ...], pad: tuple[tuple[int, int], ...] = ((0, 0), (0, 0), (0, 0)), reservoir_pad: tuple[tuple[int, int], ...] = ((0, 0), (0, 0), (0, 0))) tuple[int, ...]
Determine the start of the subdomain. used for saving as vtk.
Start is the minimum voxel ID :param index: subdomain index :type index: tuple[int, int, int]
- Returns:
start
- Return type:
tuple[int,…]
- get_padded_voxels() tuple[int, ...]
Calculate number of voxels in each subdomain.
This includes padding and reservoir.
- Returns:
Number of voxels in each dimension.
- Return type:
tuple[int, …]
- get_padding(pad: tuple[int, ...]) tuple[tuple[int, int], ...]
Compute the padding for each dimension of the subdomain.
Padding is applied to all boundaries except ‘end’ and ‘wall’ boundary types, where pad is limited to 1. Padding must be equal on opposite features.
- Parameters:
pad (tuple[int, ...]) – Pad length for each dimension.
- Returns:
Padding for each dimension.
- Return type:
tuple[tuple[int, int], …]
- get_reservoir_padding(reservoir_voxels: int) tuple[tuple[int, int], ...]
Determine inlet/outlet info and pad image (only inlet).
- Parameters:
reservoir_voxels (int) – Number of reservoir voxels to pad.
- Returns:
Reservoir padding for each dimension.
- Return type:
tuple[tuple[int, int], …]
- update_reservoir(img: ndarray[Any, dtype[T]], value: T) ndarray[Any, dtype[T]]
Enforce a constant value in reservoir regions.
- Parameters:
img (np.ndarray) – Image array to update.
value – Value to set in reservoir regions.
- Returns:
Updated image array.
- Return type:
np.ndarray
pmmoto.core.subdomain_verlet module
subdomain_verlet.py
- class pmmoto.core.subdomain_verlet.VerletSubdomain(rank: int, decomposed_domain: DecomposedDomain, verlet_domains: tuple[int, ...], pad: tuple[int, ...] = (0, 0, 0), reservoir_voxels: int = 0)
Bases:
PaddedSubdomain
Verlet subdomains divide a subdomain into smaller Verlet domains.
Initialize a PaddedSubdomain.
- Parameters:
rank (int) – Rank of the subdomain.
decomposed_domain – Decomposed domain object.
pad (tuple[int, int, int], optional) – Padding for each dimension.
reservoir_voxels (int, optional) – Reservoir voxels to pad at inlet/outlet.
- get_maximum_diameter() ndarray[Any, dtype[float64]]
Determine the maximum diameter of the verlet subdomain
- get_verlet_box() dict[int, tuple[tuple[int, int], ...]]
Determine the box of the verlet subdomain
- get_verlet_centroid() ndarray[Any, dtype[float64]]
Determine the center of the verlet domain
- get_verlet_loop() ndarray[Any, dtype[uint64]]
Collect the loop information for each verlet subdomain
- get_verlet_voxels() tuple[tuple[int, ...], ...]
Determine the number of voxels for each verlet subdomain
pmmoto.core.utils module
Core utility functions for PMMoTo.
This module provides utility functions for array manipulation, validation, MPI-aware operations, and subdomain/grid management.
- pmmoto.core.utils.bin_image(subdomain: Subdomain, img: NDArray[T], own: bool = True) dict[T, int]
Count the number of times each unique element occurs in the input array.
- Parameters:
subdomain – Subdomain object.
img (np.ndarray) – Input array.
own (bool) – If True, use only owned voxels.
- Returns:
Mapping from element value to count.
- Return type:
dict
- pmmoto.core.utils.constant_pad_img(img: ndarray[Any, dtype[T]], pad: tuple[tuple[int, int], ...], pad_value: int | float) ndarray[Any, dtype[T]]
Pad a grid with a constant value.
- Parameters:
img (np.ndarray) – Input array.
pad (list or tuple) – Padding amounts for each dimension.
pad_value (scalar) – Value to use for padding.
- Returns:
The padded array.
- Return type:
np.ndarray
- pmmoto.core.utils.determine_maximum(img: ndarray[Any, dtype[T]]) int | float
Determine the global maximum of an input image.
- Parameters:
img (np.ndarray) – Input array.
- Returns:
Global maximum value.
- Return type:
scalar
- pmmoto.core.utils.own_img(subdomain: Subdomain, img: NDArray[T], own_voxels: None | NDArray[np.integer[Any]] = None) NDArray[T]
Return array with only nodes owned by the current process.
- Parameters:
subdomain – Subdomain object with get_own_voxels method.
img (np.ndarray) – Input image.
own_voxels – NDArray of size 2*dims with bounds of image to extract
- Returns:
Array of owned voxels.
- Return type:
np.ndarray
- pmmoto.core.utils.phase_exists(img: ndarray[Any, dtype[T]], phase: int | float) bool
Determine if a phase exists in the grid (globally).
- Parameters:
img (np.ndarray) – Input array.
phase (int) – Phase value to check.
- Returns:
True if phase exists, False otherwise.
- Return type:
bool
- pmmoto.core.utils.unpad(img: ndarray[Any, dtype[T]], pad: tuple[tuple[int, int], ...]) ndarray[Any, dtype[T]]
Remove padding from a NumPy array.
- Parameters:
img (np.ndarray) – The padded array.
pad (list or tuple) – Padding
- Returns:
The unpadded array.
- Return type:
np.ndarray
pmmoto.core.voxels module
voxel.py
Core voxel operations for PMMoTo.
- pmmoto.core.voxels.count_label_voxels(img: ndarray[Any, dtype[T]], map: dict[int, int]) dict[int, int]
Count the number of voxels for each label in the grid.
- Parameters:
img – Grid array.
map – Mapping array.
- Returns:
None
- pmmoto.core.voxels.gen_img_to_label_map(img: ndarray[Any, dtype[INT]], labels: ndarray[Any, dtype[INT2]]) dict[INT2, INT]
Generate a mapping from grid indices to labels.
- Parameters:
img – Grid array.
labels – Label array.
- Returns:
Mapping array.
- pmmoto.core.voxels.gen_inlet_label_map(subdomain: Subdomain | PaddedSubdomain | VerletSubdomain, label_img: ndarray[Any, dtype[T]]) ndarray[Any, dtype[T]]
Determine which face is on inlet.
Currently restricted to a single face.
- Parameters:
subdomain – Subdomain object.
label_img – Labeled image.
- Returns:
Array of inlet labels.
- Return type:
np.ndarray
- pmmoto.core.voxels.gen_outlet_label_map(subdomain: Subdomain | PaddedSubdomain | VerletSubdomain, label_img: ndarray[Any, dtype[T]]) ndarray[Any, dtype[T]]
Determine which face is on outlet.
Currently restricted to a single face.
- Parameters:
subdomain – Subdomain object.
label_img – Labeled image.
- Returns:
Array of outlet labels.
- Return type:
np.ndarray
- pmmoto.core.voxels.get_boundary_voxels(subdomain: Subdomain | PaddedSubdomain | VerletSubdomain, img: ndarray[Any, dtype[INT]], neighbors_only: bool = False) dict[tuple[int, ...], dict[str, ndarray[Any, dtype[INT]]]]
Return the values on the boundary features.
The features are divided into: - own: feature voxels owned by subdomain - neighbor: feature voxels owned by a neighbor subdomain
- Parameters:
subdomain – Subdomain object.
img – Image array.
neighbors_only (bool) – If True, only include neighbor voxels.
- Returns:
Dictionary of boundary voxels.
- Return type:
dict
- pmmoto.core.voxels.get_id(index: tuple[int, ...], total_voxels: tuple[int, ...]) uint64
Get the global or local ID for a voxel.
- Parameters:
index – 3D index of the voxel (x, y, z).
total_voxels – Number of voxels in each dimension.
- Returns:
Global or local ID of the voxel.
- Return type:
int
Note
Periodic boundary conditions are applied by using modulo arithmetic.
- pmmoto.core.voxels.get_nearest_boundary_index(subdomain: Subdomain | PaddedSubdomain | VerletSubdomain, img: ndarray[Any, dtype[T]], label: int, dimension: None | int = None, which_voxels: Literal['all', 'own', 'pad'] = 'all') dict[tuple[int, ...], ndarray[Any, dtype[T]]]
Determine the nearest boundary index to a given label
If which_voxels == “all”, always use base version. If which_voxels is “own”/ “pad”, use extended version.
- pmmoto.core.voxels.match_global_boundary_voxels(matches: dict[tuple[int, INT], dict[str, tuple[int, INT]]], label_count: int) tuple[dict[int, dict[int, INT]], int]
Generate a global label map for matched boundary voxels.
- Parameters:
subdomain – Subdomain object.
matches – Matches dictionary.
label_count – Number of labels on this rank.
- Returns:
(final_map, global_label_count)
- Return type:
tuple
- pmmoto.core.voxels.match_neighbor_boundary_voxels(subdomain: Subdomain | PaddedSubdomain | VerletSubdomain, boundary_voxels: dict[tuple[int, ...], dict[str, ndarray[Any, dtype[INT]]]], recv_data: dict[tuple[int, ...], dict[str, ndarray[Any, dtype[INT]]]], skip_zero: bool = False) dict[tuple[int, INT], dict[str, tuple[int, INT]]]
Match boundary voxels with subdomain neighbor voxels and return unique matches.
- Parameters:
subdomain – Subdomain object containing feature information.
boundary_voxels – Dictionary with ‘own’ and ‘neighbor’ boundary voxel data.
recv_data – Received data containing neighbor voxel information.
skip_zero (bool) – If True, skip matches with label 0.
- Returns:
- Unique matches in the format:
key: (subdomain rank, own voxel) neighbor: list[neighbor rank, neighbor voxel)]
- Return type:
dict
- pmmoto.core.voxels.renumber_image(img: ndarray[Any, dtype[INT2]], conversion_map: dict[INT2, INT]) ndarray[Any, dtype[INT]]
Renumber an image using a provided mapping.
- Parameters:
img (Any) – The image to be renumbered.
conversion_map (dict) – A dictionary mapping current image IDs to new image IDs. Example: {1: 101, 2: 102, …} Note: All IDs in img must be defined in conversion_map.
- Returns:
The renumbered image, with IDs replaced based on the mapping.
- Return type:
Any
Note
This function assumes all required IDs are present in the conversion_map. No error handling is performed for missing or invalid keys.
Example
img = [[1, 2], [2, 1]] conversion_map = {1: 101, 2: 102} renumber_image(img, conversion_map) # Output: [[101, 102], [102, 101]]