Skip to content

Commit

Permalink
idaes-dev 1.6_rel branch as of d33cf8f for 1.6.0 final
Browse files Browse the repository at this point in the history
  • Loading branch information
ksbeattie committed Jul 21, 2020
1 parent c8a0897 commit c64fc9e
Show file tree
Hide file tree
Showing 21 changed files with 3,099 additions and 376 deletions.
9 changes: 7 additions & 2 deletions docs/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,12 @@ Powershell Prompt. Regardless of OS and shell, the following steps are the same

..
.. warning:: The IDAES binary extensions are not yet supported on Mac/OSX
.. warning:: The IDAES binary extensions are not yet supported on Mac/OSX.

As fallback (assuming you are uisng a conda env) you can install
the generic ipopt solver with the command ``conda install -c
conda-forge ipopt`` though this will not have all the features
of our extentions package.

.. note:: If you are installing on Linux, you can specify a specific platform.
While most Linux builds are interchangeable, specifying a build can
Expand Down Expand Up @@ -168,4 +173,4 @@ Powershell Prompt. Regardless of OS and shell, the following steps are the same
may see some "Error" level log messages, but they are okay, and produced by tests for
error handling. The number of tests that failed and succeeded is reported at the end of the pytest
output. You can report problems on the `Github issues page <https://github.com/IDAES/idaes-pse/issues>`_
(Please try to be specific about the command and the offending output.)
(Please try to be specific about the command and the offending output.)
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
FpcTP
=====

.. contents:: Contents
:depth: 2

State Definition
----------------

This approach describes the material state in terms of phase-component flow (:math:`F_{p, j}`: `flow_mol_phase_comp`), temperature (:math:`T`: `temperature`) and pressure (:math:`P`: `pressure`). As such, there are :math:`2 + phases*N_{components}` state variables.

Application
-----------

This approach required knowledge of the phase-equilibrium of the material in order to define the state variables. Compared to using total flow rate and mole fractions, this approach contains full information on the phase equilibria within the state variables, and thus avoids the needs for flash calculations in many cases. This can greatly reduce the complexity of the problem, and results can significantly affect the tractablity of the problem. However, this approach has a number of limitations which the user should be aware of:

* Users must have knowledge of , or calculate, the phase-component flows of all inlet streams. For sinlge phase flows this is often known, but for streasm with potetnial two-phase behaviour this can reqruire a set of flash calculations for the feed streasm (users can make use of Feed blocks to assist with this).
* State becomes ill-defined when only one component is present and multiphase behavior can occur, as temperature and pressure are insufficient to fully define the thermodynamic state under these conditions.

Bounds
------

The FpcTP module supports bounding of the following variables through the `state_bounds` configuration argument:

* `flow_mol_phase_comp`
* `temperature`
* `pressure`

Supporting Variables and Constraints
------------------------------------

In addition to the state variables, this definition of state creates a number of supporting variables and constraints.

Variables
"""""""""

* `mole_frac_phase_comp` (:math:`x_{p, j}`)

Expressions
"""""""""""

* `flow_mol` (:math:`F = \sum{F_{p,j}}`)
* `flow_mol_phase` (:math:`F_p = \sum{F_{p,j}}_j`)
* `flow_mol_comp` (:math:`F_j = \sum{F_{p,j}}_p`)
* `mole_frac_comp` (:math:`x_j = \frac{\sum{F_{p,j}}}{F}`)
* `phase_frac` (:math:`\psi_p = \frac{F_p}{F}` or :math:`\psi_p = 1` if only single phase)

Constraints
"""""""""""

A set of constraints is created to calculate phase-component mole fractions from the phase-component flow rates.

.. math:: F_j = x_{p, j} \times \sum{F_p} = F_{p, j}

Default Balance Types and Flow Basis
------------------------------------

The following defaults are specified for Unit Models using this state definition:

* Material balances: total component balances
* Material flow basis: molar flow
* Energy balances: total enthalpy
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ State Definition Libraries
state/FcTP
state/FPhx
state/FcPh
state/FpcTP

Setting Bounds on State Variables
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
2 changes: 1 addition & 1 deletion idaes/core/control_volume0d.py
Original file line number Diff line number Diff line change
Expand Up @@ -1031,7 +1031,7 @@ def add_total_enthalpy_balances(self,
self.heat = Var(self.flowsheet().config.time,
domain=Reals,
initialize=0.0,
doc="Heat transfered into congtrol volume",
doc="Heat transfered into control volume",
units=units['energy_flow'])

# Work transfer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,10 @@ def test_define_display_vars(self, model):

assert len(sv) == 4
for i in sv:
assert i in ["flow_mol",
"mole_frac_comp",
"temperature",
"pressure"]
assert i in ["Total Molar Flowrate",
"Total Mole Fraction",
"Temperature",
"Pressure"]

@pytest.mark.unit
def test_dof(self, model):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,10 +317,10 @@ def test_define_display_vars(self, model):

assert len(sv) == 4
for i in sv:
assert i in ["flow_mol",
"enth_mol",
"pressure",
"mole_frac_comp"]
assert i in ["Total Molar Flowrate",
"Molar Enthalpy",
"Pressure",
"Total Mole Fraction"]

@pytest.mark.unit
def test_dof(self, model):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,9 @@ def test_define_display_vars(self, model):

assert len(sv) == 3
for i in sv:
assert i in ["flow_mol_comp",
"enth_mol",
"pressure"]
assert i in ["Molar Flowrate",
"Molar Enthalpy",
"Pressure"]

@pytest.mark.unit
def test_dof(self, model):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,9 @@ def test_define_display_vars(self, model):

assert len(sv) == 3
for i in sv:
assert i in ["flow_mol_comp",
"temperature",
"pressure"]
assert i in ["Molar Flowrate",
"Temperature",
"Pressure"]

@pytest.mark.unit
def test_dof(self, model):
Expand Down
96 changes: 60 additions & 36 deletions idaes/generic_models/properties/core/generic/generic_property.py
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,8 @@ def define_metadata(cls, obj):
obj.add_properties(
{'flow_mol': {'method': None},
'flow_mol_phase': {'method': None},
'flow_mol_phase_comp': {'method': None},
'flow_mol_comp': {'method': None},
'mole_frac_comp': {'method': None},
'mole_frac_phase_comp': {'method': None},
'phase_frac': {'method': None},
Expand Down Expand Up @@ -548,12 +550,17 @@ def initialize(blk, state_args={}, state_vars_fixed=False,
flag_dict = fix_state_vars(blk, state_args)
# Confirm DoF for sanity
for k in blk.keys():
if degrees_of_freedom(blk[k]) != 0:
raise BurntToast("Degrees of freedom were not zero "
"after trying to fix state variables. "
"Something broke in the generic property "
"package code - please inform the IDAES "
"developers.")
if blk[k].always_flash:
# If not always flash, DoF is probably less than zero
# We will handle this elsewhere
dof = degrees_of_freedom(blk[k])
if dof != 0:
raise BurntToast(
"Degrees of freedom were not zero [{}] "
"after trying to fix state variables. "
"Something broke in the generic property "
"package code - please inform the IDAES "
"developers.".format(dof))
else:
# When state vars are fixed, check that DoF is 0
for k in blk.keys():
Expand Down Expand Up @@ -763,7 +770,8 @@ def initialize(blk, state_args={}, state_vars_fixed=False,
"eq_mole_frac_tbub",
"eq_mole_frac_tdew",
"eq_mole_frac_pbub",
"eq_mole_frac_pdew"):
"eq_mole_frac_pdew",
"mole_frac_comp_eq"):
c.deactivate()

# If StateBlock has active constraints (i.e. has bubble and/or dew
Expand All @@ -780,7 +788,8 @@ def initialize(blk, state_args={}, state_vars_fixed=False,
)
# ---------------------------------------------------------------------
# Calculate _teq if required
if blk[k].params.config.phases_in_equilibrium is not None:
if (blk[k].params.config.phases_in_equilibrium is not None and
(not blk[k].config.defined_state or blk[k].always_flash)):
for k in blk.keys():
for pp in blk[k].params._pe_pairs:
blk[k].params.config.phase_equilibrium_state[pp] \
Expand All @@ -806,20 +815,30 @@ def initialize(blk, state_args={}, state_vars_fixed=False,
init_log.info("State variable initialization completed.")

# ---------------------------------------------------------------------
if (blk[k].params.config.phase_equilibrium_state is not None and
(not blk[k].config.defined_state or blk[k].always_flash)):
for c in blk[k].component_objects(Constraint):
# Activate common constraints
if c.local_name in ("total_flow_balance",
"component_flow_balances",
"sum_mole_frac",
"equilibrium_constraint"):
c.activate()
for pp in blk[k].params._pe_pairs:
# Activate formulation specific constraints
blk[k].params.config.phase_equilibrium_state[pp] \
.phase_equil_initialization(blk[k], pp)
n_cons = 0
skip = False
for k in blk.keys():
if (blk[k].params.config.phase_equilibrium_state is not None and
(not blk[k].config.defined_state or blk[k].always_flash)):
for c in blk[k].component_objects(Constraint):
# Activate common constraints
if c.local_name in ("total_flow_balance",
"component_flow_balances",
"sum_mole_frac",
"equilibrium_constraint"):
c.activate()
for pp in blk[k].params._pe_pairs:
# Activate formulation specific constraints
blk[k].params.config.phase_equilibrium_state[pp] \
.phase_equil_initialization(blk[k], pp)

n_cons += number_activated_constraints(blk[k])
if degrees_of_freedom(blk[k]) < 0:
# Skip solve if DoF < 0 - this is probably due to a
# phase-component flow state with flash
skip = True

if n_cons > 0 and not skip:
with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
res = solve_indexed_blocks(opt, [blk], tee=slc.tee)
init_log.info(
Expand All @@ -837,11 +856,21 @@ def initialize(blk, state_args={}, state_vars_fixed=False,
blk[k].params.config
.state_definition.do_not_initialize):
c.activate()
with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
res = solve_indexed_blocks(opt, [blk], tee=slc.tee)
init_log.info("Property initialization: {}.".format(
idaeslog.condition(res))
)

n_cons = 0
skip = False
for k in blk:
if degrees_of_freedom(blk[k]) < 0:
# Skip solve if DoF < 0 - this is probably due to a
# phase-component flow state with flash
skip = True
n_cons += number_activated_constraints(blk[k])
if n_cons > 0 and not skip:
with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
res = solve_indexed_blocks(opt, [blk], tee=slc.tee)
init_log.info("Property initialization: {}.".format(
idaeslog.condition(res))
)

# ---------------------------------------------------------------------
# Return constraints to initial state
Expand Down Expand Up @@ -1127,8 +1156,7 @@ def rule_enth_mol_phase_comp(b, p, j):
p_config = b.params.get_phase(p).config
return p_config.equation_of_state.enth_mol_phase_comp(b, p, j)
self.enth_mol_phase_comp = Expression(
self.params.phase_list,
self.params.component_list,
self.params._phase_component_set,
rule=rule_enth_mol_phase_comp)
except AttributeError:
self.del_component(self.enth_mol_phase_comp)
Expand Down Expand Up @@ -1162,8 +1190,7 @@ def rule_entr_mol_phase_comp(b, p, j):
p_config = b.params.get_phase(p).config
return p_config.equation_of_state.entr_mol_phase_comp(b, p, j)
self.entr_mol_phase_comp = Expression(
self.params.phase_list,
self.params.component_list,
self.params._phase_component_set,
rule=rule_entr_mol_phase_comp)
except AttributeError:
self.del_component(self.entr_mol_phase_comp)
Expand All @@ -1174,8 +1201,7 @@ def _fug_phase_comp(self):
def rule_fug_phase_comp(b, p, j):
p_config = b.params.get_phase(p).config
return p_config.equation_of_state.fug_phase_comp(b, p, j)
self.fug_phase_comp = Expression(self.params.phase_list,
self.params.component_list,
self.fug_phase_comp = Expression(self.params._phase_component_set,
rule=rule_fug_phase_comp)
except AttributeError:
self.del_component(self.fug_phase_comp)
Expand All @@ -1187,8 +1213,7 @@ def rule_fug_coeff_phase_comp(b, p, j):
p_config = b.params.get_phase(p).config
return p_config.equation_of_state.fug_coeff_phase_comp(b, p, j)
self.fug_coeff_phase_comp = Expression(
self.params.phase_list,
self.params.component_list,
self.params._phase_component_set,
rule=rule_fug_coeff_phase_comp)
except AttributeError:
self.del_component(self.fug_coeff_phase_comp)
Expand Down Expand Up @@ -1222,8 +1247,7 @@ def rule_gibbs_mol_phase_comp(b, p, j):
p_config = b.params.get_phase(p).config
return p_config.equation_of_state.gibbs_mol_phase_comp(b, p, j)
self.gibbs_mol_phase_comp = Expression(
self.params.phase_list,
self.params.component_list,
self.params._phase_component_set,
rule=rule_gibbs_mol_phase_comp)
except AttributeError:
self.del_component(self.gibbs_mol_phase_comp)
Expand Down
Loading

0 comments on commit c64fc9e

Please sign in to comment.