porescene.model module

Pore Networks

class porescene.model.PoreNetwork[source]

Bases: object

A pore network model made up of pores (spheres) and throats (cylinders).

Holds the network geometry (pore/throat radii and positions, boundary pores, connectivity and coordination numbers) together with an ordered list of PoreNetworkState instances describing the network’s state variables. Use from_mat() to build an instance from a MATLAB .mat file.

classmethod from_mat(pth, vars_nwk, vars_state=(), no_states=(), *, swap_axes=True)[source]

Creates a PoreNetwork instance by importing the pore network data from a MATLAB .mat file.

Attention

Variable import from .mat files is only supported for MATLAB files in version 7.3 that are based on HDF5. When saving the MATLAB file, make sure to set the -v7.3 in MATLAB’s save function.

MATLAB
1save('myfile.mat', "-v7.3");

Attention

While the first index in MATLAB arrays is 1, Python (and numpy) arrays are 0-indexed. This importer function automatically converts the MATLAB indices into 0-based Python indices.

Note that this applies to following properties:

Attention

MATLAB stores multi-dimensional arrays in column-major order, while numpy defaults to row-major order. Dumping a voxel image out of MATLAB and reading it back with numpy (e.g. via numpy.fromfile() followed by reshape()) therefore reverses the storage order of its dimensions, which swaps the array’s first and third (spatial) axes while leaving the second axis untouched – what MATLAB calls its first dimension ends up as numpy’s third axis, and vice versa, while the second dimension stays in place.

Since porescene.utility.volume2mesh() builds its mesh directly from such a numpy voxel array, meshes it produces have their first and third axes swapped relative to the coordinate frame the .mat file’s own variables (e.g. pos_p) were written in. By default (swap_axes=True), this importer swaps the first and third columns of every imported position array (PoreNetwork.pore_position and its _top/_bottom/_left/ _right/_front/_back variants) to match, so pore/throat coordinates line up with meshes built by volume2mesh(). Pass swap_axes=False to import the coordinates verbatim in the MATLAB axis order instead, e.g. when no voxel-image mesh is involved.

Parameters:
  • pth (Path) – Path to the MATLAB .mat file.

  • vars_nwk (dict[str, str]) – A map that specifies the corresponding variables in the .mat file for the properties of the PoreNetwork instance.

  • vars_state (Sequence[StateVariableMap]) –

    The StateVariableMap instances that relate the state variables in the .mat file to PoreNetworkProperty instances.

    Each StateVariableMap carries a property name (StateVariableMap.name, identical to PoreNetworkProperty.name) together with the names of the .mat variables holding the per-pore and per-throat data (StateVariableMap.variable_sphere and StateVariableMap.variable_cylinder, respectively). A variable left as None is skipped, so a property may provide pore data, throat data, or both.

    As example: in case of "temperature" field data, the .mat file contains a variable T_pores that holds the temperature of each pore, while the variable T_throats holds the temperature values of each throat. An additional "concentration_acetone" field is added by appending a further StateVariableMap to the sequence.

    Python
    1temperature = StateVariableMap("temperature")
    2temperature.variable_sphere = "T_pores"
    3temperature.variable_cylinder = "T_throats"
    4
    5acetone = StateVariableMap("concentration_acetone")
    6acetone.variable_sphere = "C_acetone_pores"
    7acetone.variable_cylinder = "C_acetone_throats"
    8
    9vars_state = [temperature, acetone]
    

    By convention, the first array dimension is equal to the number of pores/ throats, while the second dimension contains the evolution of the field, e.g in case of the temperature field, it might be the temporal evolution (when the pore network contains 6274 pores and 149366 throats, and 1000 temperature steps have been calculated, variable T_pores has a size of 6274 × 1000 and T_throats has a size of 149366 × 1000).

  • no_states (Sequence[int]) –

    In case there is state data contained in the .mat file, the state indices given in no_states are wrapped into PoreNetworkState instances.

    For example, if 1000 states have been calculated, but only every 100th state should be visualized, then no_states could be:

    Python
    1no_states = np.linspace(0, 1000, num=10)
    

  • swap_axes (bool) – If True (default), swaps the first and third columns of every imported position array to compensate for the MATLAB/numpy axis-order mismatch described above, e.g. aligning coordinates with meshes built by porescene.utility.volume2mesh(). Set to False to import the coordinates verbatim, in the MATLAB axis order.

Returns:

PoreNetwork instance created from given .mat file

Return type:

Self

add_state(no_state)[source]

Adds a PoreNetworkState to the current model instance.

Return type:

Self

get_state(no_state)[source]

Returns a PoreNetworkState from the instance.

Return type:

PoreNetworkState

load_states_from_mat(pth_mat, vars_state, no_states)[source]

Loads state data from a MATLAB .mat file into this instance.

In contrast to from_mat(), which builds a new PoreNetwork, this method appends the requested states to an already existing instance, loading both pore and throat data for each PoreNetworkProperty.

Attention

Variable import from .mat files is only supported for MATLAB files in version 7.3 that are based on HDF5. When saving the MATLAB file, make sure to set the -v7.3 in MATLAB’s save function.

Parameters:
Returns:

This PoreNetwork instance with the loaded states added.

Return type:

Self

Raises:

ValueError – If a non-None pore or throat variable named in vars_state is not present in the .mat file.

throat_count(left=False, right=False, front=False, back=False, bottom=False, top=False)[source]

Number of throats in the network.

Parameters:
  • left (bool) – If true, outgoing throats on the left domain boundary are included in the throat count, by default False.

  • right (bool) – If true, outgoing throats on the right domain boundary are included in the throat count, by default False.

  • front (bool) – If true, outgoing throats on the front domain boundary are included in the throat count, by default False.

  • back (bool) – If true, outgoing throats on the back domain boundary are included in the throat count, by default False.

  • bottom (bool) – If true, outgoing throats on the bottom domain boundary are included in the throat count, by default False.

  • top (bool) – If true, outgoing throats on the top domain boundary are included in the throat count, by default False.

Returns:

Number of throats.

Return type:

int

property extent: ndarray

Physical dimensions (x, y, z) of the pore network domain.

property length_x: float

Physical extent of the pore network domain in first dimension.

property length_y: float

Physical extent of the pore network domain in second dimension.

property length_z: float

Physical extent of the pore network domain in third dimension.

property pnp: ndarray | None

Neighbor pores of each pore.

property pore_coordination_number: ndarray | None

Coordination number of each pore.

property pore_count: int

Number of pores in the network.

property pore_neighboring_pores: ndarray | None

Neighbor pores of each pore.

property pore_position: ndarray | None

Position of each pore.

property pore_position_back: ndarray | None

Position of each node at the sample bottom surface.

property pore_position_bottom: ndarray | None

Position of each node at the sample bottom surface.

property pore_position_front: ndarray | None

Position of each node at the sample bottom surface.

property pore_position_left: ndarray | None

Position of each node at the left sample surface.

property pore_position_right: ndarray | None

Position of each node at the right sample surface.

property pore_position_top: ndarray | None

Position of each node at the top sample surface.

property pore_radius: ndarray | None

Radius of each pore.

property pores_back: ndarray | None

Pores located at the back domain interface that have a connection to the surrounding.

property pores_bottom: ndarray | None

Pores located at the sample bottom interface that have a connection to the surrounding.

property pores_front: ndarray | None

Pores located at the front domain interface that have a connection to the surrounding.

property pores_left: ndarray | None

Pores located at the left domain interface that have a connection to the surrounding.

property pores_right: ndarray | None

Pores located at the right domain interface that have a connection to the surrounding.

property pores_top: ndarray | None

Pores located at the sample top interface that have a connection to the surrounding.

property states: list[PoreNetworkState]

The states of the pore network.

property throat_coordination_number: ndarray | None

Coordination number of each throat.

property throat_length: ndarray | None

Length of each throat.

property throat_neighboring_pores: ndarray | None

Neighbor pores of each throat.

property throat_radius: ndarray | None

Radius of each throat.

property throat_radius_back: ndarray | None

Radius of each throat connection into the surrounding at the back domain boundary.

property throat_radius_bottom: ndarray | None

Radius of each throat connection into the surrounding at the bottom domain boundary.

property throat_radius_front: ndarray | None

Radius of each throat connection into the surrounding at the front domain boundary.

property throat_radius_left: ndarray | None

Radius of each throat connection into the surrounding at the left domain boundary.

property throat_radius_right: ndarray | None

Radius of each throat connection into the surrounding at the right domain boundary.

property throat_radius_top: ndarray | None

Radius of each throat connection into the surrounding at the top domain boundary.

property tnp: ndarray | None

Neighbor pores of each throat.

class porescene.model.PoreNetworkProperty(n)[source]

Bases: object

A wrapper for a single property of one state of a pore network.

set_data(vals_p, vals_t)[source]

Sets pore and throat related data at once.

Return type:

Self

property max: float

Hightest value from all values across pores and throats.

property min: float

Lowest value from all values across pores and throats.

property name: str

Name of the property.

property pore_values: ndarray | None

Pore related data values.

property throat_values: ndarray | None

Throat related data values.

class porescene.model.PoreNetworkState[source]

Bases: object

A wrapper for one state of a pore network.

add_property(prop)[source]

Add a PoreNetworkProperty.

Return type:

Self

get_property(name)[source]

Returns a PoreNetworkProperty by name.

Return type:

PoreNetworkProperty

has_property(name)[source]

Check if the model has data about property name.

Return type:

bool

property no: int
property properties: list[PoreNetworkProperty]
property time_points: list[float]
class porescene.model.StateVariableMap(prop_name)[source]

Bases: object

Maps a pore network property to the .mat variables holding its data.

Relates a single property (identified by name) to the names of the MATLAB variables that store the property’s per-pore (sphere) and per-throat (cylinder) values, telling PoreNetwork.from_mat() and PoreNetwork.load_state_from_mat() which variables to import.

property name: str

Name of the mapped property.

property variable_cylinder: str | None

Name of the .mat variable holding the per-throat (cylinder) values, or None.

property variable_sphere: str | None

Name of the .mat variable holding the per-pore (sphere) values, or None.