Interleaving Data#

Defining Multiple Subdomains#

One of the features in OpenPNM is the ability to model heterogeneous materials by applying different pore-scale models to different regions. This is done by (a) creating a unique Geometry object for each region (i.e. small pores vs big pores) and (b) creating unique Physics object for each region as well (i.e. Knudsen diffusion vs Fickian diffusion). One consequence of this segregation of properties is that a single array containing values for all locations in the domain does not exist. OpenPNM offers a shortcut for this, known as interleave_data, which happens automatically, and makes it possible to query Geometry properties via the Network object, and Physics properties from the associated Phase object:

Let’s demonstrate this by creating a network and assigning two separate geometries to each half of the network:

[1]:
import openpnm as op
[2]:
pn = op.network.Cubic([5, 5, 5])
geo1 = op.geometry.GenericGeometry(network=pn, pores=range(0, 75),
                                   throats=range(0, 150))
geo2 = op.geometry.GenericGeometry(network=pn, pores=range(75, 125),
                                   throats=range(150, 300))
geo1['pore.diameter'] = 1.0
geo2['pore.diameter'] = 0.1

Each of the Geometry objects has a ‘pore.diameter’ array with different values. To obtain a single array of ‘pore.diameter’ with values in the correct locations, we can use the Network as follows:

[3]:
Dp = pn['pore.diameter']
print(Dp[70:80])
[1.  1.  1.  1.  1.  0.1 0.1 0.1 0.1 0.1]

As can be seen, the ‘pore.diameter’ array contains values from both Geometry objects, and they are in their correction locations in terms of the domain number system. This is referred to as interleave_data. It also works to obtain Physics values via their associated Phase object.

Interleaving of data also works in the reverse direction, so that data only present on the network can be accessed via the Geometry objects:

[4]:
coords = geo1['pore.coords']
print(coords[0:3])
[[0.5 0.5 0.5]
 [0.5 0.5 1.5]
 [0.5 0.5 2.5]]

Finally, interleave_data works between objects of the same type, so that if ‘pore.volume’ is present on one but not another Geometry object, you will get an array of NaNs when asking for it on the object that does not have it:

[5]:
geo1['pore.volume'] = 3.0
print(geo2['pore.volume'][:5])
[nan nan nan nan nan]

Points to Note#

  • Data cannot be written in this way, so that you cannot write ‘pore.diameter’ values to the Network if ’pore.diameter is already present on a Geometry (e.g. pn[‘pore.diameter’] = 2.0 will result in an error)

  • Interleaving data is automatically attempted if the requested key is not found. For instance, when you request pn['pore.diameter'] it is not found, so a search is made of the associated Geometry objects and if found an array is built.

  • If an array named ‘pore.foo’ is already present on the Network or Phase, it cannot be created on a Geometry or Physics, resepctively, since this would break the automated interleave_data mechanism, which searches for arrays called ‘pore.foo’ on all associated objects