[OpenPNM] Part 3——Labels and Domains

Please refresh the page if equations are not rendered correctly.
---------------------------------------------------------------

Labels

使用网络模型自带的标签

import openpnm as op
import numpy as np
op.visualization.set_mpl_style()
pn = op.network.Cubic(shape=[5, 5, 1])
ax = op.visualization.plot_coordinates(pn)#将pore可视化为点
ax = op.visualization.plot_connections(pn, ax=ax)#可视化流道为线
op.visualization.plot_tutorial(pn);
print(pn)


print(pn['pore.coords'])
print(pn.Ps)
print(pn['pore.left'])
'''
[[0.5 0.5 0.5]
[0.5 1.5 0.5]
[0.5 2.5 0.5]
[0.5 3.5 0.5]
[0.5 4.5 0.5]
[1.5 0.5 0.5]
[1.5 1.5 0.5]
[1.5 2.5 0.5]
[1.5 3.5 0.5]
[1.5 4.5 0.5]
[2.5 0.5 0.5]
[2.5 1.5 0.5]
[2.5 2.5 0.5]
[2.5 3.5 0.5]
[2.5 4.5 0.5]
[3.5 0.5 0.5]
[3.5 1.5 0.5]
[3.5 2.5 0.5]
[3.5 3.5 0.5]
[3.5 4.5 0.5]
[4.5 0.5 0.5]
[4.5 1.5 0.5]
[4.5 2.5 0.5]
[4.5 3.5 0.5]
[4.5 4.5 0.5]]
[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
24]
[ True  True  True  True  True False False False False False False False
False False False False False False False False False False False False
False]
'''


np.where有两种用法
1.np.where(condition,x,y) 当where内有三个参数时，第一个参数表示条件，当条件成立时where方法返回x，当条件不成立时where返回y
2.np.where(condition) 当where内只有一个参数时，那个参数表示条件，当条件成立时，where返回的是每个符合condition条件元素的坐标,返回的是以元组的形式

np.where(pn['pore.left'])[0]
'''
array([0, 1, 2, 3, 4])
'''


np.where()[0] 和 np.where()[1]的具体使用见：https://blog.csdn.net/weixin_38346042/article/details/119181014

corner_pores = pn['pore.left']*pn['pore.front']
print(np.where(corner_pores)[0])
'''
[0]
'''


The and methods

pn.pores(['left', 'back']，mode='or')
'''
[ 0  1  2  3  4  9 14 19 24]
'''


pn.pores(['left', 'back']，mode='and')
'''
[4]
'''


pn.pores(['left', 'back'], mode='nor')
'''
array([ 5,  6,  7,  8, 10, 11, 12, 13, 15, 16, 17, 18, 20, 21, 22, 23])
'''


mode='xor'意思是“检索所有有'左'的'后'的孔，但不能同时检索两者”

pn.pores(['left', 'back'], mode='xor')
'''
array([ 0,  1,  2,  3,  9, 14, 19, 24])
'''


mode='nand'表示“检索只满足一个给定标签的所有孔隙指数”

pn.pores(['left', 'right'], mode='nand')
array([ 0,  1,  2,  3,  4, 20, 21, 22, 23, 24])


mode='xnor',查询具有多个给定标签的孔

pn.pores(['left', 'back'], mode='xnor')
array([4])


自定义标签

Ps = Ps = pn.pores(['left', 'front'], mode='and')
pn.set_label(label='corner', pores=Ps)
print(pn.pores('corner'))
'''
[0]
'''

set_label(self, label, pores=None, throats=None, mode='add'):
r"""
Creates or updates a label array

Parameters
----------
label : str
The label to apply to the specified locations
pores : array_like
A list of pore indices or a boolean mask of where given label
should be added or removed (see mode)
throats : array_like
A list of throat indices or a boolean mask of where given label
should be added or removed (see mode)
mode : str
Controls how the labels are handled.  Options are:

=========== ======================================================
mode        description
=========== ======================================================
locations while keeping existing labels

'overwrite' Removes existing label from all locations before
adding the label in the specified locations

'remove'    Removes the given label from the specified locations
leaving the remainder intact

'purge'     Removes the specified label from the object completely.
This ignores the pores and throats arguments.

'clear'     Sets all the labels to False but does not remove
the label array
=========== ======================================================

"""


使用 @ sytax 读取和写入数据

@ 语法提供了读取和写入标签下的数据的快捷方式。@ 语法也用于定义孔隙网络属性不同的domain，但首先让我们看一下使用 @：

pn['pore.coords@left']
'''
[[0.5 0.5 0.5]
[0.5 1.5 0.5]
[0.5 2.5 0.5]
[0.5 3.5 0.5]
[0.5 4.5 0.5]]
'''


@ sytax 也可用于写入数据。让我们创建一个 1.0 的数组，然后使用 @ 语法更改它们：

pn['pore.values'] = 1.0
print(pn['pore.values'])
pn['pore.values@left'] = 2.0
print(pn['pore.values'])
pn['pore.values@right'] = [4, 5, 6, 7, 8]
print(pn['pore.values'])
'''
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.
1.]
[2. 2. 2. 2. 2. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.
1.]
[2. 2. 2. 2. 2. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 4. 5. 6. 7.
8.]
'''


pn['pore.new_array@left'] = 2.0
print(pn['pore.new_array'])
#上行创建了一个空数组，然后把2.0赋值给标记为left的孔中,其他未赋值的孔默认为nan
pn['pore.new_array@front'] = 3.0
print(pn['pore.new_array'])
print(pn['pore.new_array@left'])
'''
[ 2.  2.  2.  2.  2. nan nan nan nan nan nan nan nan nan nan nan nan nan
nan nan nan nan nan nan nan]
[ 3.  2.  2.  2.  2.  3. nan nan nan nan  3. nan nan nan nan  3. nan nan
nan nan  3. nan nan nan nan]
[3. 2. 2. 2. 2.]
'''


定义子域

pn.add_model(propname='pore.seed',
model=op.models.geometry.pore_seed.random,
domain='left',
seed=0,
num_range=[0.1, 0.5])

"""
Add a pore-scale model to the object, along with the desired arguments

Parameters
----------
propname : str
The name of the property being computed. E.g. if
propname='pore.diameter' then the computed results will be stored
in obj['pore.diameter'].
model : function handle
The function that produces the values
domain : str
The label indicating the locations in which results generated by
model should be stored. See Notes for more details.
regen_mode : str
How the model should be regenerated. Options are:

============ =====================================================
regen_mode   description
============ =====================================================
normal       (default) The model is run immediately upon being
added, and is also run each time regenerate_models
is called.
deferred     The model is NOT run when added, but is run each time
regenerate_models is called. This is useful for
models that depend on other data that may not exist
yet.
constant     The model is run immediately upon being added, but is
is not run when regenerate_models is called,
effectively turning the property into a constant.
============ =====================================================

kwargs : keyword arguments
All additional keyword arguments are passed on to the model

Notes
-----
The domain argument dictates where the results of model should
be stored. For instance, given propname='pore.diameter' and
domain='left' then when model is run, the results are stored in
in the pores labelled left. Note that if model returns Np
values, then values not belonging to 'pore.left' are discarded.
The following steps outline the process:

1. Find the pore indices:

.. code-block:: python

Ps = obj.pores('left')

2. Run the model:

.. code-block:: python

vals = model(**kwargs)

3. If the model returns a full Np-length array, then extract the
correct values and apply them to the corresponding locations:

.. code-block:: python

if len(vals) == obj.Np:
obj['pore.diameter'][Ps] = vals[Ps]

4. If the model was designed to return only the subset of values then:

.. code-block:: python

if len(vals) == obj.num_pores('left'):
obj['pore.diameter'][Ps] = vals

"""


pn.add_model(propname='pore.seed',
model=op.models.geometry.pore_seed.random,
domain='right',
seed=0,
num_range=[0.5, 0.9])

#现在，这些值存在于 10 个位置。pore.seed'

print(pn)


print(pn.models)


定义和更改子域位置

pn.pores('left')
#array([0, 1, 2, 3, 4])
pn['pore.left'][[4, 5]] = True
del pn['pore.seed']
pn.run_model('pore.seed@left')
print(pn)


混合完整域和子域模型

#首先删除上面应用的各个模型，并将它们替换为在所有位置上应用统一值的单个模型，然后将两个不同的正态分布应用于  'left' 和 'right'

del pn.models['pore.seed@left']
del pn.models['pore.seed@right']
model=op.models.geometry.pore_seed.random)
model=op.models.geometry.pore_size.normal,
domain='left',
scale=0.1,
loc=1,
seeds='pore.seed')
model=op.models.geometry.pore_size.normal,
domain='right',
scale=2,
loc=10,
seeds='pore.seed')

import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 2, figsize=[12, 6])

ax[0].plot(pn.Ps, pn['pore.seed'], 'o')
ax[0].set_ylabel('pore seed')
ax[0].set_xlabel('pore index')

ax[1].plot(pn.pores('left'), pn['pore.diameter@left'], 'o', label='pore.left')
ax[1].plot(pn.pores('right'), pn['pore.diameter@right'], 'o', label='pore.right')
ax[1].set_ylabel('pore diameter')
ax[1].set_xlabel('pore index')
ax[1].legend();


pn.add_model(propname='pore.volume',
model=op.models.geometry.pore_volume.sphere)
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 1, figsize=[6, 6])

ax.plot(pn.Ps, pn['pore.volume'], 'o')
ax.set_ylabel('pore volume')
ax.set_xlabel('pore index');


混合许多不同形状的子域

Ps = pn.pores(['front', 'back'])
pn['throat.front'] = Ts
pn['throat.back'] = ~Ts
model=op.models.geometry.throat_size.from_neighbor_pores,
domain='front',
mode='min')