Skip to content

Commit

Permalink
getting tighter now
Browse files Browse the repository at this point in the history
  • Loading branch information
jgostick committed Jul 7, 2022
1 parent e86b437 commit f98d8ac
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 51 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,4 @@ openpnm/core/.DS_Store
*/.DS_Store
*.DS_Store
*.nblink
.idea
6 changes: 4 additions & 2 deletions openpnm/core/_base2.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,11 @@ def __getitem__(self, key):
# meant for exploring the idea of putting phase values in the
# network dict, like pn['pore.temperature.air'], but we're not doing
# that now.
if '*' in key:
if key.startswith('*'):
d = {}
key = key[1:]
key = key[1:] # Remove astrisk
if key.startswith('.'): # Remove leading dot if *. was given
key = key[1:]
for k, v in self.items():
if k.endswith(key):
d[k[:-len(key)-1]] = super().__getitem__(k)
Expand Down
2 changes: 1 addition & 1 deletion openpnm/models/collections/phase/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
from .water import water
from .mercury import mercury
from .liquid_mixture import liquid_mixture
from .gas_mixture import gas_mixture
from .gas_mixture import binary_gas_mixture, gas_mixture
28 changes: 25 additions & 3 deletions openpnm/models/collections/phase/gas_mixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
from openpnm.utils import get_model_collection


def gas_mixture(regen_mode=None, domain=None):
return get_model_collection(collection=_gas_mixture,
def binary_gas_mixture(regen_mode=None, domain=None):
return get_model_collection(collection=_binary_gas_mixture,
regen_mode=regen_mode,
domain=domain)


_gas_mixture = {
_binary_gas_mixture = {
'pore.molecular_weight': {
'model': mods.mixtures.mixture_molecular_weight,
},
Expand All @@ -34,3 +34,25 @@ def gas_mixture(regen_mode=None, domain=None):
'model': mods.diffusivity.gas_mixture_diffusivity,
},
}


def gas_mixture(regen_mode=None, domain=None):
return get_model_collection(collection=_gas_mixture,
regen_mode=regen_mode,
domain=domain)


_gas_mixture = {
'pore.molecular_weight': {
'model': mods.mixtures.mixture_molecular_weight,
},
'pore.viscosity': {
'model': mods.viscosity.gas_mixture_viscosity,
},
'pore.thermal_conductivity': {
'model': mods.thermal_conductivity.gas_mixture_thermal_conductivity,
},
'pore.heat_capacity': {
'model': mods.heat_capacity.mixture_heat_capacity,
},
}
11 changes: 6 additions & 5 deletions openpnm/models/phase/diffusivity/_funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ def gas_mixture_LJ_epsilon(target):
Calculates the effective molecular diameter for a binary mixture
"""
es = [c['param.lennard_jones_epsilon'] for c in target.components.values()]
assert len(es) == 2
eAB = np.sqrt(np.prod(es))
return eAB

Expand Down Expand Up @@ -344,13 +345,13 @@ class MixDict(dict):
only two components of a mixture that has several. This is necessary for
use of the fuller model for calculating binary diffusivities.
"""

def __init__(self, target, components):
super().__init__(target)
self.components = {}
for item in components:
self.components.update({item.name: item})


comps = list(target.components.values())
values = {}
for i in range(len(comps)):
Expand All @@ -361,10 +362,10 @@ def __init__(self, target, components):
B = comps[j]
temp = MixDict(target=target, components=(A, B))
D = fuller_mixture(target=temp,
molecular_weight=molecular_weight,
molar_diffusion_volume=molar_diffusion_volume,
temperature=temperature,
pressure=pressure)
molecular_weight=molecular_weight,
molar_diffusion_volume=molar_diffusion_volume,
temperature=temperature,
pressure=pressure)
yB = target['pore.mole_fraction.' + B.name]
denom += yB/D
yA = target['pore.mole_fraction.' + A.name]
Expand Down
114 changes: 93 additions & 21 deletions openpnm/phase/_mixture.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import numpy as np
import logging
from copy import deepcopy
from openpnm.phase import Phase
from openpnm.models.collections.phase import liquid_mixture, gas_mixture
from openpnm.models.collections.phase import liquid_mixture
from openpnm.models.collections.phase import gas_mixture, binary_gas_mixture
from openpnm.models.phase.mixtures import mole_summation
from openpnm.utils import HealthDict, PrintableList, SubDict
from openpnm.utils import HealthDict
from openpnm.utils import Docorator, Workspace


Expand All @@ -15,22 +15,14 @@

__all__ = [
'Mixture',
'GasMixture',
'BinaryGasMixture',
'MultiGasMixture',
'LiquidMixture',
]


class MixtureSettings:
r"""
The following settings are specific to Mixture objects
Parameters
----------
components : list of strings
The names of each pure component object that constitute the mixture
"""
components = []
...


@docstr.get_sections(base='Mixture', sections=['Parameters'])
Expand Down Expand Up @@ -64,10 +56,21 @@ def __getitem__(self, key):
if key.split('.')[-1] in self.components.keys():
comp = self.project[key.split('.')[-1]]
vals = comp[key.rsplit('.', maxsplit=1)[0]]
elif key.endswith('*'):
key = key[:-1]
if key.endswith('.'):
key = key[:-1]
vals = self._get_comp_vals(key)
else:
raise KeyError(key)
return vals

def _get_comp_vals(self, propname):
vals = {}
for comp in self.components.keys():
vals[comp] = self[propname + '.' + comp]
return vals

def __str__(self):
horizontal_rule = '―' * 78
temp = super().__str__().split(horizontal_rule)
Expand Down Expand Up @@ -101,8 +104,13 @@ def _set_comps(self, components):
def add_comp(self, component, mole_fraction=0.0):
self['pore.mole_fraction.' + component.name] = mole_fraction

def remove_comp(self, compname):
del self['pore.mole_fraction.' + compname]
def remove_comp(self, component):
if hasattr(component, 'name'):
component = component.name
try:
del self['pore.mole_fraction.' + component]
except KeyError:
pass

def check_mixture_health(self):
r"""
Expand Down Expand Up @@ -133,6 +141,7 @@ def check_mixture_health(self):


class LiquidMixture(Mixture):

def __init__(self, **kwargs):
super().__init__(**kwargs)
self.models.update(liquid_mixture())
Expand Down Expand Up @@ -171,10 +180,6 @@ def x(self, compname=None, x=None):


class GasMixture(Mixture):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.models.update(gas_mixture())
self.regenerate_models()

def y(self, compname=None, y=None):
r"""
Expand Down Expand Up @@ -208,13 +213,80 @@ def y(self, compname=None, y=None):
self['pore.mole_fraction.' + compname] = y


class MultiGasMixture(GasMixture):

def __init__(self, **kwargs):
super().__init__(**kwargs)
self.models.clear()
self.models.update(gas_mixture())
self.regenerate_models()

class BinaryGasMixture(GasMixture):

def __init__(self, **kwargs):
super().__init__(**kwargs)
self.models.clear()
self.models.update(binary_gas_mixture())
self.regenerate_models()

def add_comp(self, component, mole_fraction=0.0):
if len(self['pore.mole_fraction'].keys()) >= 2:
raise Exception("Binary mixtures cannot have more than 2 components"
+ ", remove one first")
super().add_component(component=component, mole_fraction=mole_fraction)


if __name__ == '__main__':
import openpnm as op
pn = op.network.Demo()
o2 = op.phase.GasByName(network=pn, species='o2', name='pure_O2')
n2 = op.phase.GasByName(network=pn, species='n2', name='pure_N2')
air = op.phase.GasMixture(network=pn, components=[o2, n2])
air = op.phase.BinaryGasMixture(network=pn, components=[o2, n2], name='air')
air.y(o2.name, 0.21)
air['pore.mole_fraction.pure_N2'] = 0.79
air.regenerate_models()
print(air)

ch4 = op.phase.GasByName(network=pn, species='ch4', name='methane')
h2 = op.phase.GasByName(network=pn, species='h2', name='hydrogen')
h2o = op.phase.GasByName(network=pn, species='h2o', name='water')
co2 = op.phase.GasByName(network=pn, species='co2', name='co2')
syngas = op.phase.MultiGasMixture(network=pn, components=[ch4, h2, h2o, co2],
name='syngas')
syngas.y(h2.name, 0.25)
syngas.y(ch4.name, 0.25)
syngas.y(h2o.name, 0.25)
syngas.y(co2.name, 0.25)
syngas.regenerate_models()
print(syngas)































32 changes: 18 additions & 14 deletions openpnm/phase/_species.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def mixture(self):
for comp in item.components.values():
if self is comp:
return item
logger.warn("No mixture phase found for this species")


class SpeciesByName(Species):
Expand All @@ -61,22 +62,25 @@ class SpeciesByName(Species):
"""

def __init__(self, species, **kwargs):
super().__init__(**kwargs)
# Create temp first to ensure all look-ups pass before initializing obj
temp = {}
CAS = chem.CAS_from_any(species)
self['param.CAS'] = CAS
temp['param.CAS'] = CAS
a = chem.identifiers.search_chemical(CAS)
self['param.common_name'] = a.common_name
self['param.molecular_weight'] = a.MW/1000 # Convert to kg/mol
self['param.critical_temperature'] = chem.critical.Tc(CAS)
self['param.critical_pressure'] = chem.critical.Pc(CAS)
self['param.critical_volume'] = chem.critical.Vc(CAS)
self['param.critical_compressibilty_factor'] = chem.critical.Zc(CAS)
self['param.boiling_temperature'] = chem.Tb(CAS)
self['param.melting_temperature'] = chem.Tm(CAS)
self['param.acentric_factor'] = chem.acentric.omega(CAS)
self['param.dipole_moment'] = chem.dipole.dipole_moment(CAS)
self['param.lennard_jones_epsilon'] = k*chem.lennard_jones.Stockmayer(CAS)
self['param.lennard_jones_sigma'] = chem.lennard_jones.molecular_diameter(CAS)
temp['param.common_name'] = a.common_name
temp['param.molecular_weight'] = a.MW/1000 # Convert to kg/mol
temp['param.critical_temperature'] = chem.critical.Tc(CAS)
temp['param.critical_pressure'] = chem.critical.Pc(CAS)
temp['param.critical_volume'] = chem.critical.Vc(CAS)
temp['param.critical_compressibilty_factor'] = chem.critical.Zc(CAS)
temp['param.boiling_temperature'] = chem.Tb(CAS)
temp['param.melting_temperature'] = chem.Tm(CAS)
temp['param.acentric_factor'] = chem.acentric.omega(CAS)
temp['param.dipole_moment'] = chem.dipole.dipole_moment(CAS)
temp['param.lennard_jones_epsilon'] = k*chem.lennard_jones.Stockmayer(CAS)
temp['param.lennard_jones_sigma'] = chem.lennard_jones.molecular_diameter(CAS)
super().__init__(**kwargs)
self._params.update(temp)


class GasByName(SpeciesByName):
Expand Down
9 changes: 4 additions & 5 deletions tests/unit/phase/MixtureTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,13 @@ def test_set_component_by_property(self):
del self.air['pore.mole_fraction.pure_CO2']
assert len(self.air.components) == 2

def test_set_component_method(self):
def test_add_and_remove_component_method(self):
net = op.network.Demo()
o2 = op.phase.GasByName(network=net, species='o2', name='pure_O2')
n2 = op.phase.GasByName(network=net, species='n2', name='pure_N2')
air = op.phase.GasMixture(network=net)
air.y(o2.name, 0.21)
air['pore.mole_fraction.pure_N2'] = 0.79
air.regenerate_models()
air = op.phase.GasMixture(network=net, components=[n2, o2])
air.remove_comp(n2)
air.remove_component(o2)

def test_check_health(self):
self.air['pore.mole_fraction.pure_N2'] = 0.79
Expand Down

0 comments on commit f98d8ac

Please sign in to comment.