From ca2c217269875b3a3da23035765d9e4a9efd0c9f Mon Sep 17 00:00:00 2001 From: Doug A Date: Mon, 14 Aug 2023 11:21:53 -0400 Subject: [PATCH] towards a better behaved model --- idaes/models/unit_models/separator.py | 180 +++++++++--------- .../solid_oxide_module_simple.py | 17 +- 2 files changed, 101 insertions(+), 96 deletions(-) diff --git a/idaes/models/unit_models/separator.py b/idaes/models/unit_models/separator.py index e7a119eee6..ecabd3b7f9 100644 --- a/idaes/models/unit_models/separator.py +++ b/idaes/models/unit_models/separator.py @@ -1258,7 +1258,7 @@ def partition_outlet_flows(self, mb, outlet_list): # Add empty Port objects for o in outlet_list: - p_obj = Port(noruleinit=True, doc="Outlet Port") + p_obj = Port(doc="Outlet Port") setattr(self, o, p_obj) # Iterate over members to create References or Expressions @@ -1453,38 +1453,40 @@ def e_rule(b, t, j): return self.eps else: + def e_rule_factory(l_name_alias): + def e_rule(b, t, j): + mfp = mb[t].component( + "{0}_phase{1}".format(l_name_alias[:-5], l_name_alias[-5:]) + ) - def e_rule(b, t, j): - mfp = mb[t].component( - "{0}_phase{1}".format(l_name[:-5], l_name[-5:]) - ) - - if mfp is None: - _raise_split_indexed_fail_err(self.name, s) + if mfp is None: + _raise_split_indexed_fail_err(self.name, s) - for p in mb.phase_list: - if (p, j) in pc_set: - if ( - self.config.split_basis - == SplittingType.phaseFlow - ): - s_check = split_map[p] - elif ( - self.config.split_basis - == SplittingType.phaseComponentFlow - ): - s_check = split_map[p, j] - else: - raise BurntToast( - "{} This should not happen. Please" - " report this bug to the IDAES " - "developers.".format(self.name) - ) + for p in mb.phase_list: + if (p, j) in pc_set: + if ( + self.config.split_basis + == SplittingType.phaseFlow + ): + s_check = split_map[p] + elif ( + self.config.split_basis + == SplittingType.phaseComponentFlow + ): + s_check = split_map[p, j] + else: + raise BurntToast( + "{} This should not happen. Please" + " report this bug to the IDAES " + "developers.".format(self.name) + ) - if s_check == o: - return mfp[p, j] - # else: - return self.eps + if s_check == o: + return mfp[p, j] + return self.eps + return e_rule + e_rule = e_rule_factory(l_name) + e_obj = VarLikeExpression( self.flowsheet().time, @@ -1493,78 +1495,82 @@ def e_rule(b, t, j): ) else: - # Unindexed variable - def e_rule(b, t): - if self.config.split_basis == SplittingType.phaseFlow: - ivar = mb[t].component(l_name + "_phase") - if ivar is not None: - for p in mb.phase_list: - if split_map[p] == o: - return ivar[p] - else: - continue - else: - ivar = mb[t].component(l_name + "_phase_comp") + # Variable unindexed by phase or component + def e_rule_factory(l_name_alias): + def e_rule(b, t): + if self.config.split_basis == SplittingType.phaseFlow: + ivar = mb[t].component(l_name_alias + "_phase") if ivar is not None: for p in mb.phase_list: if split_map[p] == o: - return sum( - ivar[p, j] - for j in mb.component_list - if (p, j) in pc_set - ) + return ivar[p] else: continue else: - _raise_split_unindexed_fail_err(self.name, s) - - elif self.config.split_basis == SplittingType.componentFlow: - ivar = mb[t].component(l_name + "_comp") - if ivar is not None: - for j in mb.component_list: - if split_map[j] == o: - return ivar[j] + ivar = mb[t].component(l_name_alias + "_phase_comp") + if ivar is not None: + for p in mb.phase_list: + if split_map[p] == o: + return sum( + ivar[p, j] + for j in mb.component_list + if (p, j) in pc_set + ) + else: + continue else: - continue - else: - ivar = mb[t].component(l_name + "_phase_comp") + _raise_split_unindexed_fail_err(self.name, s) + + elif self.config.split_basis == SplittingType.componentFlow: + ivar = mb[t].component(l_name_alias + "_comp") if ivar is not None: for j in mb.component_list: if split_map[j] == o: - return sum( - ivar[p, j] - for p in mb.phase_list - if (p, j) in pc_set - ) + return ivar[j] else: continue + else: + ivar = mb[t].component(l_name_alias + "_phase_comp") + if ivar is not None: + for j in mb.component_list: + if split_map[j] == o: + return sum( + ivar[p, j] + for p in mb.phase_list + if (p, j) in pc_set + ) + else: + continue + else: + _raise_split_unindexed_fail_err(self.name, s) + elif ( + self.config.split_basis + == SplittingType.phaseComponentFlow + ): + ivar = mb[t].component(l_name_alias + "_phase_comp") + if ivar is not None: + for p in mb.phase_list: + for j in mb.component_list: + if ( + split_map[p, j] == o + and (p, j) in pc_set + ): + return ivar[p, j] + else: + continue else: _raise_split_unindexed_fail_err(self.name, s) - elif ( - self.config.split_basis - == SplittingType.phaseComponentFlow - ): - ivar = mb[t].component(l_name + "_phase_comp") - if ivar is not None: - for p in mb.phase_list: - for j in mb.component_list: - if ( - split_map[p, j] == o - and (p, j) in pc_set - ): - return ivar[p, j] - else: - continue else: - _raise_split_unindexed_fail_err(self.name, s) - else: - # Unrecognised split tupe - raise BurntToast( - "{} received unrecognised value for " - "split_basis argument. This should never " - "happen, so please contact the IDAES " - "developers with this bug.".format(self.name) - ) + # Unrecognised split tupe + raise BurntToast( + "{} received unrecognised value for " + "split_basis argument. This should never " + "happen, so please contact the IDAES " + "developers with this bug.".format(self.name) + ) + return e_rule + + e_rule = e_rule_factory(l_name) e_obj = VarLikeExpression(self.flowsheet().time, rule=e_rule) diff --git a/idaes/models_extra/power_generation/unit_models/soc_submodels/solid_oxide_module_simple.py b/idaes/models_extra/power_generation/unit_models/soc_submodels/solid_oxide_module_simple.py index ce65ff2f25..8384aa7f78 100644 --- a/idaes/models_extra/power_generation/unit_models/soc_submodels/solid_oxide_module_simple.py +++ b/idaes/models_extra/power_generation/unit_models/soc_submodels/solid_oxide_module_simple.py @@ -43,6 +43,9 @@ __author__ = "Douglas Allan" + +from functools import partial + from pyomo.common.config import ConfigValue, ConfigBlock import pyomo.environ as pyo @@ -198,14 +201,14 @@ def rule_mole_frac(blk, t, port, comps): self, f"{port_name}_temperature_eqn", pyo.Constraint( - tset, rule=lambda blk, t: rule_temperature(blk, t, props, port) + tset, rule=partial(rule_temperature, props=props, port=port) ), ) setattr( self, f"{port_name}_pressure_eqn", pyo.Constraint( - tset, rule=lambda blk, t: rule_pressure(blk, t, props, port) + tset, rule=partial(rule_pressure, props=props, port=port) ), ) setattr( @@ -214,9 +217,7 @@ def rule_mole_frac(blk, t, port, comps): pyo.Constraint( tset, side_comps, - rule=lambda blk, t, j: rule_flow_mol_comp( - blk, t, j, props, port - ), + rule=partial(rule_flow_mol_comp, props=props, port=port), ), ) if direction == "in": @@ -225,9 +226,7 @@ def rule_mole_frac(blk, t, port, comps): f"{port_name}_mole_frac_eqn", pyo.Constraint( tset, - rule=lambda blk, t: rule_mole_frac( - blk, t, port, side_comps - ), + rule=partial(rule_mole_frac, port=port, comps=side_comps), ), ) if direction == "out": @@ -237,7 +236,7 @@ def rule_mole_frac(blk, t, port, comps): pyo.Constraint( tset, absent_comp_list, - rule=lambda blk, t, j: rule_absent_comp(blk, t, j, props), + rule=partial(rule_absent_comp, props=props), ), ) # Add a different port at the module level