Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add documentation and change the name of ion_dspmde #858

Merged
merged 37 commits into from
Nov 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
4c82a3c
init
lbibl Oct 14, 2022
73ed889
docs/technical_reference/property_models/DSPMDE.rst
lbibl Nov 22, 2022
5393ec0
save work
lbibl Nov 24, 2022
885a544
save work
lbibl Nov 27, 2022
b5efcbf
rough draft completed, changed pp name
lbibl Nov 27, 2022
2dbd4df
change doc name
lbibl Nov 27, 2022
da30320
add index
lbibl Nov 27, 2022
13ef1af
save work
lbibl Nov 27, 2022
b9eed9e
changed all dspmde names
lbibl Nov 27, 2022
55c554d
debug
lbibl Nov 27, 2022
d5108b8
sphinx debug
lbibl Nov 27, 2022
03a49cb
sphinx debug
lbibl Nov 27, 2022
4430a07
format improvement
lbibl Nov 28, 2022
5dbe49a
format improvement
lbibl Nov 28, 2022
2557283
format improvement
lbibl Nov 28, 2022
67cf2ed
sphinx debug
lbibl Nov 28, 2022
d3f447b
sphinx debug
lbibl Nov 28, 2022
ee0d095
sphinx debug
lbibl Nov 28, 2022
1bc0a91
sphinx debug
lbibl Nov 28, 2022
c210974
sphinx debug
lbibl Nov 28, 2022
c3506bf
sphinx debug
lbibl Nov 28, 2022
3b15118
sphinx debug
lbibl Nov 28, 2022
310e172
sphinx debug
lbibl Nov 28, 2022
0026395
sphinx debug
lbibl Nov 28, 2022
ae6b0f7
format
lbibl Nov 28, 2022
88f4d4b
format
lbibl Nov 28, 2022
a0a1cce
format
lbibl Nov 28, 2022
9b76534
format
lbibl Nov 28, 2022
08b7e3b
format
lbibl Nov 28, 2022
1141f9b
merge upstream main
lbibl Nov 28, 2022
2fb4ae9
test black format for doc
lbibl Nov 28, 2022
0661812
missed name change
lbibl Nov 28, 2022
edfbd4c
missed name change
lbibl Nov 28, 2022
a09e580
Merge branch 'main' into dspmde_doc
bknueven Nov 30, 2022
bc73ae3
Merge remote-tracking branch 'upstream/main' into dspmde_doc
bknueven Nov 30, 2022
d70e5f9
merge recent wtorg changes to address conflicts
lbibl Nov 30, 2022
cb25d4d
address conflicts
lbibl Nov 30, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/technical_reference/property_models/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ Property Models
coagulation
ASM1
ASM2D

mc_aq_sol
133 changes: 133 additions & 0 deletions docs/technical_reference/property_models/mc_aq_sol.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
Multi-Component Aqueous Solution (MCAS) Property Package
=========================================================

This property package implements property relationships for an aqueous solution that may contain multiple neutral and/or ionic solutes.

This MCAS property package
* sets H2O as the solvent;
* supports multiple solute components including ions and neutral molecules;
* supports only liquid phase;
* uses molar flow rate (in mol/s), temperature and pressure as the initial state variables;
* does not support dynamics.

Classes
-------
.. currentmodule:: watertap.property_models.multicomp_aq_sol_prop_pack

.. autoclass:: MCASParameterBlock
:members:
:noindex:

.. autoclass:: MCASParameterData
:members:
:noindex:

.. autoclass:: _MCASStateBlock
:members:
:noindex:

.. autoclass:: MCASStateBlockData
:members:
:noindex:

Sets
----
.. csv-table::
:header: "Description", "Symbol", "Members"

"AqueousPhase", ":math:`p`", "{'Liq'}"
"component_list", ":math:`j`", "{'H2O', solute_list :sup:`1`}"
"solute_set", ":math:`j`", "{neutral species in solute_list} :sup:`2`"
"ion_set", ":math:`j`", "{ionic species in solute_list}"
"cation_set", ":math:`j`", "{cationic species in solute_list}"
"anion_set", ":math:`j`", "{anionic species in solute_list}"

**Notes**
:sup:`1` solute_list is provided by a necessary configuration to use this property package.
:sup:`2` In the implementing codes, the "solute_set" was declared to include only neutral species for current programming convenience; in other places throughout this document, "solute" by itself includes both ionic and neutral species solvated by water.

State variables
---------------
.. csv-table::
:header: "Description", "Symbol", "Coded Var Name", "Index", "Unit"

"Component molar flow rate", ":math:`N`", "flow_mol_phase_comp", "[p, j]", ":math:`\text{mol s}^{-1}`"
"Temperature", ":math:`T`", "temperature", "None", ":math:`\text{K}`"
"Pressure", ":math:`P`", "pressure", "None", ":math:`\text{Pa}`"

Calculated Properties
---------------------
.. csv-table::
:header: "Description", "Symbol", "Coded Var Name", "Index", "Unit", "Calculation Methods"

"Component mass flow rate", ":math:`M`", "flow_mass_phase_comp", "[p, j]", ":math:`\text{kg s}^{-1}`", ":math:`M=Nm_N`"
"Component charge-equivalent molar flow rate", ":math:`\tilde{N}`", "flow_equiv_phase_comp", "[p, j]", ":math:`\text{mol s}^{-1}`", ":math:`\tilde{N}=N\left|z\right|`"
"Component charge-equivalent molar concentration", ":math:`\tilde{n}`", "conc_equiv_phase_comp", "[p, j]", ":math:`\text{mol m}^{-3}`", ":math:`\tilde{n}=n\left|z\right|`"
"Component mass fraction", ":math:`x`", "mass_frac_phase_comp", "[p, j]", ":math:`\text{dimensionless}`", ":math:`x_j=\frac{M_j}{\sum_j{M_j}}`"
"Mass density of aqueous phase", ":math:`\rho`", "dens_mass_phase", "[p]", ":math:`\text{kg m}^{-3}`", ":math:`\rho=1000 \text{kg m}^{-3}` or :math:`\rho=\rho_w + \textbf{f} \left(\sum_{j\in solute}{x_j}, T\right)` :sup:`1`"
"Mass density of solvent water", ":math:`\rho_w`", "dens_mass_w_phase", "[p]", ":math:`\text{kg m}^{-3}`",":math:`\rho_w=\textbf{f}\left(T\right)` :sup:`1`"
"Phase volumetric flowrate", ":math:`Q`", "flow_vol_phase", "[p]", ":math:`\text{m}^3\text{ } \text{s}^{-1}`", ":math:`Q=\frac{\sum_j{N_j m_{Nj}}}{\rho}`"
"Total volumetric flowrate", ":math:`Q_{tot}`", "flow_vol", "None", ":math:`\text{m}^3\text{ } \text{s}^{-1}`",":math:`Q_{tot}=\sum_p{Q_p}`"
"Component molar concentration", ":math:`n`", "conc_mol_phase_comp", "[p, j]", ":math:`\text{mol m}^{-3}`",":math:`nm_N=m`"
"Component mass concentration", ":math:`m`", "conc_mass_phase_comp", "[p, j]", ":math:`\text{kg m}^{-3}`",":math:`m=\rho x`"
"Component molar fraction", ":math:`y`", "mole_frac_phase_comp", "[p, j]", ":math:`\text{dimensionless}`", ":math:`y_j=\frac{N_j}{\sum_j{N_j}}`"
"Component molality", ":math:`b`", "molality_phase_comp", "[p, j]", ":math:`\text{mol kg}^{-1}`",":math:`b=\frac{N}{N_{H_2O} m_{N\text{H_2O}}}`"
"Component diffusivity", ":math:`D`", "diffus_phase_comp", "[p, j]", ":math:`\text{m}^2 \text{ } \text{s}^{-1}`", ":math:`D=` input from users"
"Dynamic viscosity", ":math:`\mu`", "visc_d_phase", "[p]", ":math:`\text{Pa s}`", ":math:`\mu=` input from users"
"Kinematic viscosity", ":math:`\nu`", "visc_k_phase", "[p]", ":math:`\text{m}^2 \text{ s}^{-1}`",":math:`\nu=\mu\rho^{-1}`"
"Phase osmotic pressure", ":math:`\Pi`", "pressure_osm_phase", "[p]", ":math:`\text{Pa}`",":math:`\Pi=RT\sum_{j\in solute}{n_j}`"
"Component stokes radius", ":math:`r_h`", "radius_stokes_comp", "[j]", ":math:`\text{m}`", ":math:`r_h=` input from users"
"Component molecular weight", ":math:`m_N`", "mw_comp", "[j]", ":math:`\text{kg mol}^{-1}`",":math:`m_N=` input from users"
"Ion component electrical mobility", ":math:`\mu_e`", "elec_mobility_phase_comp", "[p,j]", ":math:`\text{m}^2\text{ }\text{V}^{-1}\text{ }\text{s}^{-1}`", ":math:`\mu_e=` input from users or :math:`\mu_e=\frac{D\left|z\right|F}{RT}`"
"Ion component transport number", ":math:`t`", "trans_num_phase_comp", "[p, j]", ":math:`\text{dimensionless}`", ":math:`t=` input from users or :math:`t_j=\frac{\left|z_j\right|\mu_{ej} n_j}{\sum_{j\in ion}{\left|z_j\right|\mu_{ej} n_j}}`"
"Phase equivalent conductivity", ":math:`\Lambda`", "equiv_conductivity_phase", "[p]", ":math:`\text{m}^2 \text{ } \Omega^{-1} \text{ mol}^{-1}`", ":math:`\Lambda=` input from users or :math:`\Lambda=\frac{\sum_{j\in ion}{F\left|z_j\right|\mu_{ej} n_j}}{\sum_{j\in cation}{\left|z_j\right|n_j}}`"
"Phase electrical conductivity", ":math:`\lambda`", "elec_cond_phase", "[p]", ":math:`\Omega^{-1} \text{ m}^{-1}`", ":math:`\lambda=\Lambda\sum_{j\in cation}{\left|z_j\right|n_j}`"
"Ion component charge", ":math:`z`", "charge_comp", "[j]", ":math:`\text{dimensionless}`", ":math:`z=` input from users"
"Component activity coefficient", ":math:`\gamma`", "act_coeff_phase_comp", "[j]", ":math:`\text{dimensionless}`", ":math:`\gamma=` input from users"
"Dielectric constant", ":math:`\epsilon`", "dielectric_constant", "none", ":math:`\text{dimensionless}`", ":math:`\epsilon=` input from users"
"Debye-Huckel constant", ":math:`A`", "deby_huckel_constant", "none", ":math:`\text{dimensionless}`", ":math:`A=\frac{\left(2 \pi N_A\right)^{0.5}}{log(10)} \left(\frac{\textbf{e}^2}{4 \pi \epsilon \epsilon_0 kT}\right)^{\frac{3}{2}}`"
"Ionic Strength", ":math:`I`", "ionic_strength_molal", "none", ":math:`\text{mol kg}^{-1}`", ":math:`I=0.5\sum_{j\in ion}{z_j^2b_j}`"

**Notes**
:sup:`1` :math:`\textbf{f}(\cdot)` refers to empirical correlations of phase or solvent mass density to seawater salinity and temperature following the study of Sharqawy et al. (2010).

Physical/chemical constants
---------------------------
.. csv-table::
:header: "Description", "Symbol", "Value", "Unit"

"Idea gas constant", ":math:`R`", "8.3145", ":math:`\text{J mol}^{-1} \text{K}^{-1}`"
"Faraday constant", ":math:`F`", "96485.33", ":math:`\text{C mol}^{-1}`"
"Avogadro constant", ":math:`N_A`", "6.022e23", ":math:`\text{dimensionless}`"
"Boltzmann constant", ":math:`k`", "1.381e-23", ":math:`\text{J K}^{-1}`"
"Vacuum permittivity", ":math:`\epsilon_0`", "8.854e-12", ":math:`\text{F m}^{-1}`"
"Elementary charge", ":math:`\textbf{e}`", "1.602e-19", ":math:`\text{C}`"

Scaling
-------
A comprehensive scaling factor calculation method is coded in this property package. Among the state variables (:math:`N, T, \text{and } p`), default scaling factors for :math:`T` and :math:`p` were set and do not need users' input, while, for :math:`N`, usually require a user input via an interface. The coding interface to set defalut scaling factor for :math:`N` and call the scaling calculation for other variables is the following.

.. code-block::

m.fs.properties.set_default_scaling('flow_mol_phase_comp', 1e2, index=('Liq','{component name}'))
# m is the model name, and fs is the instanced flowsheet block of m.
calculate_scaling_factors(m)

Users also have the authority to set a scaling factor for non-state variables via the following codes:

.. code-block::

import idaes.core.util.scaling as iscale #import the needed utility package
...
iscale.set_scaling_factor(m.fs.properties.{property_name}, 100)

Proper scaling of variables is, in many cases, crucial to solver's performance in finding an optimal solution of a problem. While designing scaling can have a mathematical sophistication, a general rule is to scale all variables as close to 1 as possible, e.g., in the range of 1e-2 to 1e2.


Reference
---------

M.H. Sharqawy, J.H.L. V, S.M. Zubair, Thermophysical properties of seawater: a review of existing correlations and data, Desalination and Water Treatment. 16 (2010) 354–380. https://doi.org/10.5004/dwt.2010.1079. (2017 corrections provided at http://web.mit.edu/seawater )

Bard, A. J., Faulkner, L. R., & White, H. S. (2022). Electrochemical methods: fundamentals and applications. John Wiley & Sons.

Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
from watertap.costing.watertap_costing_package import (
WaterTAPCosting,
)
from watertap.property_models.ion_DSPMDE_prop_pack import DSPMDEParameterBlock
from watertap.property_models.multicomp_aq_sol_prop_pack import MCASParameterBlock

__author__ = "Xiangyu Bi"

Expand Down Expand Up @@ -70,7 +70,7 @@ def build():
"elec_mobility_data": {("Liq", "Na_+"): 5.19e-8, ("Liq", "Cl_-"): 7.92e-8},
"charge": {"Na_+": 1, "Cl_-": -1},
}
m.fs.properties = DSPMDEParameterBlock(**ion_dict)
m.fs.properties = MCASParameterBlock(**ion_dict)
m.fs.costing = WaterTAPCosting()
m.fs.feed = Feed(property_package=m.fs.properties)
m.fs.separator = Separator(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
WaterTAPCosting,
make_capital_cost_var,
)
from watertap.property_models.ion_DSPMDE_prop_pack import DSPMDEParameterBlock
from watertap.property_models.multicomp_aq_sol_prop_pack import MCASParameterBlock
import watertap.examples.flowsheets.electrodialysis.electrodialysis_1stack as edfs

__author__ = "Xiangyu Bi"
Expand All @@ -69,7 +69,7 @@ def test_build_model(self, electrodialysis_1D1stack):
# Test basic build
assert isinstance(m, ConcreteModel)
assert isinstance(m.fs, FlowsheetBlock)
assert isinstance(m.fs.properties, DSPMDEParameterBlock)
assert isinstance(m.fs.properties, MCASParameterBlock)
assert isinstance(m.fs.costing, Block)
assert isinstance(m.fs.feed, Feed)
assert isinstance(m.fs.separator, Separator)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@
#
###############################################################################
"""
Initial property package for multi-ionic system for use in the
Donnan Steric Pore Model with Dielectric Exclusion (DSPM-DE)
This property package computes a multi-component aqueous solution that can
contain ionic and/or neutral solute species. It supports basic calculation
of component quanitities and some physical, chemical and electrical properties.

This property package was formerly named as "ion_DSPMDE_prop_pack" for its use of
Donnan Steric Pore Model with Dielectric Exclusion (DSPMDE).
"""

# TODO:
Expand Down Expand Up @@ -101,8 +105,8 @@ class TransportNumberCalculation(Enum):
ElectricalMobility = auto()


@declare_process_block_class("DSPMDEParameterBlock")
class DSPMDEParameterData(PhysicalParameterBlock):
@declare_process_block_class("MCASParameterBlock")
class MCASParameterData(PhysicalParameterBlock):
CONFIG = PhysicalParameterBlock.CONFIG()

CONFIG.declare(
Expand Down Expand Up @@ -262,7 +266,7 @@ def build(self):
"""
super().build()

self._state_block_class = DSPMDEStateBlock
self._state_block_class = MCASStateBlock

# phases
self.Liq = AqueousPhase()
Expand Down Expand Up @@ -495,10 +499,10 @@ def define_metadata(cls, obj):
)


class _DSPMDEStateBlock(StateBlock):
class _MCASStateBlock(StateBlock):
"""
This Class contains methods which should be applied to Property Blocks as a
whole, rather than individual elements of indexed Property Blocks.
This Class contains methods which should be applied to Property Blocks as a whole, rather
than individual elements of indexed Property Blocks.
"""

def initialize(
Expand All @@ -512,44 +516,38 @@ def initialize(
):
"""
Initialization routine for property package.

Keyword Arguments:
state_args : Dictionary with initial guesses for the state vars
chosen. Note that if this method is triggered
through the control volume, and if initial guesses
were not provided at the unit model level, the
control volume passes the inlet values as initial
guess.The keys for the state_args dictionary are:

flow_mol_phase_comp : value at which to initialize
phase component flows
pressure : value at which to initialize pressure
temperature : value at which to initialize temperature
chosen. Note that if this method is triggered through the control
volume, and if initial guesses were not provided at the unit model
level, the control volume passes the inlet values as initial guess.
The keys for the state_args dictionary are:
flow_mol_phase_comp : value to initialize phase component flows;
pressure : value at which to initialize pressure;
temperature : value at which to initialize temperature.
outlvl : sets output level of initialization routine (default=idaeslog.NOTSET)
optarg : solver options dictionary object (default=None)
state_vars_fixed: Flag to denote if state vars have already been
fixed.
- True - states have already been fixed by the
control volume 1D. Control volume 0D
does not fix the state vars, so will
be False if this state block is used
with 0D blocks.
- False - states have not been fixed. The state
block will deal with fixing/unfixing.
solver : Solver object to use during initialization if None is provided
it will use the default solver for IDAES (default = None)
state_vars_fixed : Flag to denote if state vars have already
been fixed.
- True - states have already been fixed by the control volume
1D. Control volume 0D does not fix the state vars, so will be
False if this state block is used with 0D blocks.
- False - states have not been fixed. The state block will deal
with fixing/unfixing.
solver : Solver object to use during initialization. If None
is provided, it will use the default solver for IDAES (default = None)
hold_state : flag indicating whether the initialization routine
should unfix any state variables fixed during
initialization (default=False).
- True - states variables are not unfixed, and
a dict of returned containing flags for
which states were fixed during
initialization.
- False - state variables are unfixed after
initialization by calling the
release_state method
- True - state variables are not unfixed, and a dict of returned
containing flags for which states were fixed during initialization.
- False - state variables are unfixed after initialization by calling
the release_state method.

Returns:
If hold_states is True, returns a dict containing flags for
which states were fixed during initialization.
If hold_states is True, returns a dict containing flags for which states were fixed
during initialization.
"""
# Get loggers
init_log = idaeslog.getInitLogger(self.name, outlvl, tag="properties")
Expand Down Expand Up @@ -761,20 +759,23 @@ def calculate_state(
optarg=None,
):
"""
Solves state blocks given a set of variables and their values. These variables can
be state variables or properties. This method is typically used before
initialization to solve for state variables because non-state variables (i.e. properties)
cannot be fixed in initialization routines.
Solves state blocks given a set of variables and their values. These variables can be
state variables or properties. This method is typically used before initialization to
solve for state variables because non-state variables (i.e. properties) cannot be fixed
in initialization routines.

Keyword Arguments:
var_args : dictionary with variables and their values, they can be state variables or properties
var_args : dictionary with variables and their values, they
can be state variables or properties
{(VAR_NAME, INDEX): VALUE}
hold_state : flag indicating whether all of the state variables should be fixed after calculate state.
hold_state : flag indicating whether all of the state
variables should be fixed after calculate state.
True - State variables will be fixed.
False - State variables will remain unfixed, unless already fixed.
outlvl : idaes logger object that sets output level of solve call (default=idaeslog.NOTSET)
solver : solver name string if None is provided the default solver
for IDAES will be used (default = None)
outlvl : idaes logger object that sets output level of solve
call (default=idaeslog.NOTSET)
solver : solver name string if None is provided the default
solver for IDAES will be used (default = None)
optarg : solver options dictionary object (default={})

Returns:
Expand Down Expand Up @@ -862,8 +863,8 @@ def calculate_state(
return results


@declare_process_block_class("DSPMDEStateBlock", block_class=_DSPMDEStateBlock)
class DSPMDEStateBlockData(StateBlockData):
@declare_process_block_class("MCASStateBlock", block_class=_MCASStateBlock)
class MCASStateBlockData(StateBlockData):
def build(self):
"""Callable method for Block construction."""
super().build()
Expand Down Expand Up @@ -1303,7 +1304,7 @@ def _ionic_strength_molal(self):
def rule_ionic_strength_molal(b):
return b.ionic_strength_molal == 0.5 * sum(
b.charge_comp[j] ** 2 * b.molality_phase_comp["Liq", j]
for j in self.params.ion_set | self.params.solute_set
for j in self.params.ion_set
)

self.eq_ionic_strength_molal = Constraint(rule=rule_ionic_strength_molal)
Expand Down
Loading