# [OpenPNM] Part 4 ——Phases

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

# Creating Phases

OpenPNM中的所有模拟最终都需要知道流体和相的物理和热力学性质。OpenPNM提供了在子模块中计算这些值的框架，以及一组用于预测纯相和混合物性质的基本函数。因为我们不可能支持详尽的物理属性库，所以我们的策略是提供一组合理的默认函数作为一个近似值。当需要更精确的值时，可以使用许多其他包

# The classPhase（基础相）

import openpnm as op
import numpy as np
op.visualization.set_mpl_style()
#所有模拟都从定义/创建网络开始。首先创建了一个简单的立方网络，其中包含各种有用的几何属性：Demo

pn = op.network.Demo(shape=[2, 2, 1])
#定义网络后，它作为参数传递给网络模型。

phase1 = op.phase.Phase(network=pn)
print(phase1)


## 直接赋值

phase1['pore.viscosity'] = 0.001  # Pa.s
'''

'''
phase1['pore.viscosity']
array([0.001, 0.001, 0.001, 0.001])


## 使用OpenPNM自带的内置模型

OpenPNM 中的库包含一些可以使用的通用模型，例如多项式或线性线。四阶多项式可以拟合粘度与温度的实验数据，产生以下系数：

phase1['pore.viscosity'] = 0.001  # Pa.s
a4 = 5.8543E-11
a3 = -7.6756E-08
a2 = 3.7831E-05
a1 = -8.3156E-03
a0 = 6.8898E-01
#这些可以在模型中使用，如下所示：op.models.misc.polynomial

print('Before:', phase1['pore.viscosity'])
f = op.models.misc.polynomial
'''
define: polynomial(target, a, prop):

Calculates a property as a polynomial function of a given property

Parameters

target : Base
The object for which these values are being calculated.  Thiscontrols the length of the calculated array, and also provides access to other necessary thermofluid properties.
a : array_like
A list containing the polynomial coefficients, where element 0 in the list corresponds to a0 and so on.  Note that no entries can be skipped so 0 coefficients must be sent as 0.
prop : str
The dictionary key containing the independent variable or phaseproperty to be used in the polynomial.

Returns

value : ndarray
Array containing Pn(target[prop]), where Pn is nth order polynomial with coefficients stored in a.
'''
model=f,
a = (a0, a1, a2, a3, a4),
prop='pore.temperature')
print('After:', phase1['pore.viscosity'])
Before: [0.001 0.001 0.001 0.001]
After: [0.00091476 0.00091476 0.00091476 0.00091476]


model=f,
a = (a0, a1, a2, a3, a4),
prop='pore.temperature'
regen_mode='deferred' )

print('Before:', phase1['pore.viscosity'])
phase1['pore.temperature'] = 300.0 + np.random.rand(pn.Np)*50
'''
random.rand(d0, d1, ..., dn)
Random values in a given shape.
Create an array of the given shape and populate it with random samples from a uniform distribution over [0, 1).

Parameters:
d0, d1, …, dnint, optional
The dimensions of the returned array, must be non-negative. If no argument is given a single Python float is returned.

Returns:
outndarray, shape (d0, d1, ..., dn)
Random values.
'''
phase1.regenerate_models()
print('After:', phase1['pore.viscosity'])
'''
Before: [0.00091476 0.00091476 0.00091476 0.00091476]
After: [0.00066419 0.00077815 0.00065211 0.00060267]
'''


## 使用特定相模型例如‘水’

#由于水在模拟中非常常见，OpenPNM具有一些可直接使用的属性功能。例如，不需要手动输入数据并去合粘度对于温度的 n 次多项式，因为已经提供了：

print('Before:', phase1['pore.viscosity'])
f = op.models.phase.viscosity.water_correlation
#Calculates viscosity of pure water or seawater at atmospheric pressure.

model=f)
print('After:', phase1['pore.viscosity'])
'''
Before: [0.0007246  0.00050654 0.00081815 0.00047741]
After: [0.00069612 0.00047515 0.00079382 0.00044681]
'''


## 自定义模型

def custom_mu(phase, temperature='pore.temperature'):
T = phase[temperature]
a4 = 5.8543E-11
a3 = -7.6756E-08
a2 = 3.7831E-05
a1 = -8.3156E-03
a0 = 6.8898E-01
mu = a0 + a1*T + a2*T**2 + a3*T**3 + a4*T**4
return mu

model=custom_mu)
print(phase1['pore.viscosity'])
#[0.0007246  0.00050654 0.00081815 0.00047741]


## 常见流体的类

water = op.phase.Water(network=pn)
print(water)


print(water.models)


# 相的种类和多相流设置

## 纯相

o2 = op.phase.Species(network=pn, species='oxygen')
print(o2)


print(o2.params)


#这些参数用于各种属性估计方法。例如，为了计算氧气的粘度，OpenPNM提供了一个函数来实现Stiel和Thodos（）的模型：

f = op.models.phase.viscosity.gas_pure_st
model=f)
print(o2['pore.viscosity'])
'''
[2.01023694e-05 2.01023694e-05 2.01023694e-05 2.01023694e-05]
'''
#此功能需要几条热力学信息，例如临界温度和临界压力。您可以在下面看到所有参数

print(o2.models)


op.models.phase.viscosity.gas_pure_st(
phase,
T='pore.temperature',
Tc='param.critical_temperature',
Pc='param.critical_pressure',
MW='param.molecular_weight',):

Calculates the viscosity of a pure gas using the correlation in:
Sharqawy M. H., Lienhard J. H., and Zubair, S. M., Desalination and Water Treatment, 2010.

#当我们重新生成模型时，m模型将获取每个孔隙个体的临界温度值，并重新计算粘度值：

o2.regenerate_models()
print(o2['pore.viscosity'])
'''
[2.01023694e-05 2.01023694e-05 2.01023694e-05 2.01023694e-05]
'''


## 气相和液相

OpenPNM有一套计算纯相性质的函数，但这些函数对于气体和液体是不同的。因此，我们为气体和液体提供了两个类，并已经定义了适当的模型。这些被称为StandardLiquid和StandardGas，以表明所使用的模型是提供第一近似的标准选择:

o2 = op.phase.StandardGas(network=pn, species='o2')
h2o = op.phase.StandardLiquid(network=pn, species='h2o')
print(o2)


print(h2o)


print(h2o.models)


## 单相混合物

o2 = op.phase.StandardGas(network=pn, species='o2', name='oxygen')
n2 = op.phase.StandardGas(network=pn, species='n2', name='nitrogen')
air = op.phase.StandardGasMixture(network=pn, components=[o2, n2])
air.y(o2, 0.21)
air.y(n2, 0.79)
air.regenerate_models()
print(air)


print(o2['pore.viscosity'])
print('Before:', air['pore.viscosity'])
air.y(o2, 0.8)
air.y(n2, 0.2)
air.regenerate_models()
print('After:', air['pore.viscosity'])
'''
[2.01023694e-05 2.01023694e-05 2.01023694e-05 2.01023694e-05]
Before: [1.78543425e-05 1.78543425e-05 1.78543425e-05 1.78543425e-05]
After: [2.01881831e-05 2.01881831e-05 2.01881831e-05 2.01881831e-05]
'''


print(air['pore.mole_fraction'])
{'oxygen': array([0.8, 0.8, 0.8, 0.8]), 'nitrogen': array([0.2, 0.2, 0.2, 0.2])}

print(air['pore.mole_fraction'][o2.name])
#[0.8 0.8 0.8 0.8]

air['pore.mole_fraction'].keys()
#dict_keys(['oxygen', 'nitrogen'])

air.components
'''
{'oxygen': oxygen : ,
'nitrogen': nitrogen : }
'''

air.y()
'''
{'oxygen': array([0.8, 0.8, 0.8, 0.8]),
'nitrogen': array([0.2, 0.2, 0.2, 0.2])}
'''
air.y(o2.name)
#array([0.8, 0.8, 0.8, 0.8])


## 单相混合物的相关操作

### 删除

air.remove_comp(o2.name)
air.components
'''
{'nitrogen': nitrogen : }
'''

#当且仅当出现在混合物字典中时，纯相物质被视为混合物的组成部分。从字典中添加和删除相应的数组实际上是重新定义混合物的组成。'pore.mole_fraction.'
del air['pore.mole_fraction.' + n2.name]
air.components
'''
{}
'''

#可以以相同的方式重新添加它们：
air['pore.mole_fraction.' + o2.name] = 0.21
air.components
'''
{'oxygen': oxygen : }
'''

#还有一个特定的方法：
air.components
'''
{'oxygen': oxygen : ,
'nitrogen': nitrogen : }
'''


### 报告混合物属性 info

air.info
'''
══════════════════════════════════════════════════════════════════════════════
mixture_01 :
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
#  Properties                                                   Valid Values
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
2  pore.temperature                                                    4 / 4
3  pore.pressure                                                       4 / 4
4  pore.heat_capacity                                                  4 / 4
5  pore.thermal_conductivity                                           4 / 4
6  pore.viscosity                                                      4 / 4
7  pore.density                                                        4 / 4
8  pore.mole_fraction.oxygen                                           4 / 4
9  pore.mole_fraction.nitrogen                                         4 / 4
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
#  Labels                                                 Assigned Locations
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
2  pore.all                                                                4
3  throat.all                                                              4
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
Component Phases
══════════════════════════════════════════════════════════════════════════════
oxygen :
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
#  Properties                                                   Valid Values
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
2  pore.temperature.oxygen                                             4 / 4
3  pore.pressure.oxygen                                                4 / 4
4  pore.heat_capacity_gas.oxygen                                       4 / 4
5  pore.heat_capacity.oxygen                                           4 / 4
6  pore.thermal_conductivity.oxygen                                    4 / 4
7  pore.viscosity.oxygen                                               4 / 4
8  pore.density.oxygen                                                 4 / 4
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
#  Labels                                                 Assigned Locations
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
2  pore.all.oxygen                                                         4
3  throat.all.oxygen                                                       4
══════════════════════════════════════════════════════════════════════════════
nitrogen :
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
#  Properties                                                   Valid Values
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
2  pore.temperature.nitrogen                                           4 / 4
3  pore.pressure.nitrogen                                              4 / 4
4  pore.heat_capacity_gas.nitrogen                                     4 / 4
5  pore.heat_capacity.nitrogen                                         4 / 4
6  pore.thermal_conductivity.nitrogen                                  4 / 4
7  pore.viscosity.nitrogen                                             4 / 4
8  pore.density.nitrogen                                               4 / 4
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
#  Labels                                                 Assigned Locations
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
2  pore.all.nitrogen                                                       4
3  throat.all.nitrogen                                                     4
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
'''


### 获取单相混合物的组分

pore.mole_fraction

air['pore.mole_fraction']
'''
{'oxygen': array([0.21, 0.21, 0.21, 0.21]),
'nitrogen': array([0.79, 0.79, 0.79, 0.79])}
'''


component

d = air.components
print(d.keys())
'''
dict_keys(['oxygen', 'nitrogen'])
'''


### 用get_comp_vals获取组分的属性

mus = air.get_comp_vals('pore.viscosity')
print(mus)
'''
{'oxygen': array([2.09391006e-05, 2.09391006e-05, 2.09391006e-05, 2.09391006e-05]), 'nitrogen': array([1.69779528e-05, 1.69779528e-05, 1.69779528e-05, 1.69779528e-05])}
'''

#也可以通过询问混合物并附加组件名称来检索组件的属性，如下所示：
air['pore.viscosity.' + o2.name]
'''
array([2.09391006e-05, 2.09391006e-05, 2.09391006e-05, 2.09391006e-05])
'''



### 检查一致性check_mixture_health

#例如是否所有摩尔分数加起来每个孔 1.0：

print(air.check_mixture_health())
'''
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
Key                                 Value
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
mole_fraction_too_low               []
mole_fraction_too_high              []
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
'''
air.y(o2.name, 0.1)#检查o2含量是否过低（o2含量默认为0.21）
print(air.check_mixture_health())
'''
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
Key                                 Value
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
mole_fraction_too_low               (4,)
mole_fraction_too_high              []
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
'''


### 使用wildcard () syntax：*

air['pore.viscosity.*']
'''
{'oxygen': array([2.09391006e-05, 2.09391006e-05, 2.09391006e-05, 2.09391006e-05]),
'nitrogen': array([1.69779528e-05, 1.69779528e-05, 1.69779528e-05, 1.69779528e-05])}
'''