-
Notifications
You must be signed in to change notification settings - Fork 238
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding StreamScaler unit model, along with the test and rst file. (#1517
) * pull from MEA development branch * Added test file for StreamScaler unit model and added the unit model to the init file * pull from MEA development branch * Added test file for StreamScaler unit model and added the unit model to the init file * Added rst file for Stream Scaler Unit Model * Added stream_scaler.rst to the table of contents * Created the rst file for the stream_scaler unit model * Changed the default timeout time from 180 seconds -> 360 seconds due to build.py timing out * Reformatted with Black * Removed unused code flagged by Pylint * Removed unused code flagged by Pylint * Removed unused code flagged by Pylint * Removed unused code flagged by Pylint * Added StreamScalerData class to the init file for unit models * Added Tanner Polley as a co-author * Adjusted the details of the additional constraints * Resolved the test_solution method for btx and removed the comment for no solve or numerical tests to be done for the iapws since the unit model has no unit model level contraints. Tried to run the test_solve but got no feasible solution * Ran Black on these files * Fixed degrees of freedom on doc file * Revised the documentation for Degrees of Freedom for Stream Scaler * Removed unnecessary comments --------- Co-authored-by: Doug A <[email protected]> Co-authored-by: dallan-keylogic <[email protected]> Co-authored-by: Ludovico Bianchi <[email protected]>
- Loading branch information
1 parent
b032b22
commit e8c9712
Showing
6 changed files
with
658 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
46 changes: 46 additions & 0 deletions
46
docs/reference_guides/model_libraries/generic/unit_models/stream_scaler.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
Stream Scaler Block | ||
=================== | ||
|
||
Stream Scaler Blocks are used to adjust size of streams to represent, for example, a stream being split across several identical units, which are then all modeled as a single IDAES unit | ||
|
||
Degrees of Freedom | ||
------------------ | ||
|
||
Stream Scaler blocks have one degree of freedom (beyond the state variables in the ``StateBlock`` properties), a ``Var`` called ``multiplier``. It is the factor by which extensive state variables (defined as those having "flow" in their name) are scaled, with ``output_var = multiplier * input_var``. | ||
|
||
Model Structure | ||
--------------- | ||
|
||
Stream Scaler Blocks consists of a single ``StateBlock`` (named properties), each with an inlet and outlet port. | ||
|
||
Additional Constraints | ||
---------------------- | ||
|
||
Stream Scaler Blocks write no additional constraints* (besides those naturally occurring in ``StateBlocks``). | ||
|
||
Variables | ||
--------- | ||
|
||
Stream Scaler blocks add no additional Variables. | ||
|
||
.. module:: idaes.models.unit_models.stream_scaler | ||
|
||
|
||
Initialization | ||
-------------- | ||
|
||
.. autoclass:: StreamScalerInitializer | ||
:members: initialization_routine | ||
|
||
StreamScaler Class | ||
------------------ | ||
|
||
.. autoclass:: StreamScaler | ||
:members: | ||
|
||
StreamScalerData Class | ||
---------------------- | ||
|
||
.. autoclass:: StreamScalerData | ||
:members: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,244 @@ | ||
################################################################################# | ||
# The Institute for the Design of Advanced Energy Systems Integrated Platform | ||
# Framework (IDAES IP) was produced under the DOE Institute for the | ||
# Design of Advanced Energy Systems (IDAES). | ||
# | ||
# Copyright (c) 2018-2023 by the software owners: The Regents of the | ||
# University of California, through Lawrence Berkeley National Laboratory, | ||
# National Technology & Engineering Solutions of Sandia, LLC, Carnegie Mellon | ||
# University, West Virginia University Research Corporation, et al. | ||
# All rights reserved. Please see the files COPYRIGHT.md and LICENSE.md | ||
# for full copyright and license information. | ||
################################################################################# | ||
""" | ||
Unit model to adjust size of streams to represent, for example, a stream being split across several identical units, | ||
which are then all modeled as a single IDAES unit | ||
""" | ||
from functools import partial | ||
|
||
from pyomo.environ import ( | ||
Block, | ||
PositiveReals, | ||
units as pyunits, | ||
Var, | ||
) | ||
from pyomo.network import Port | ||
from pyomo.common.config import ConfigBlock, ConfigValue, In | ||
|
||
from idaes.core import ( | ||
declare_process_block_class, | ||
UnitModelBlockData, | ||
useDefault, | ||
) | ||
from idaes.core.util.config import ( | ||
is_physical_parameter_block, | ||
) | ||
from idaes.core.base.var_like_expression import VarLikeExpression | ||
from idaes.core.util.tables import create_stream_table_dataframe | ||
import idaes.core.util.scaling as iscale | ||
import idaes.logger as idaeslog | ||
|
||
from idaes.models.unit_models.feed import FeedInitializer as StreamScalerInitializer | ||
|
||
__author__ = "Douglas Allan, Tanner Polley" | ||
|
||
|
||
# Set up logger | ||
_log = idaeslog.getLogger(__name__) | ||
|
||
|
||
@declare_process_block_class("StreamScaler") | ||
class StreamScalerData(UnitModelBlockData): | ||
""" | ||
Unit model to adjust size of streams to represent, for example, a stream being split across several identical units, | ||
which are then all modeled as a single IDAES unit | ||
""" | ||
|
||
default_initializer = StreamScalerInitializer | ||
|
||
CONFIG = ConfigBlock() | ||
CONFIG.declare( | ||
"dynamic", | ||
ConfigValue( | ||
domain=In([False]), | ||
default=False, | ||
description="Dynamic model flag - must be False", | ||
doc="""Indicates whether this model will be dynamic or not, | ||
**default** = False. Scaler blocks are always steady-state.""", | ||
), | ||
) | ||
CONFIG.declare( | ||
"has_holdup", | ||
ConfigValue( | ||
default=False, | ||
domain=In([False]), | ||
description="Holdup construction flag - must be False", | ||
doc="Scaler blocks do not contain holdup, thus this must be False.", | ||
), | ||
) | ||
CONFIG.declare( | ||
"property_package", | ||
ConfigValue( | ||
default=useDefault, | ||
domain=is_physical_parameter_block, | ||
description="Property package to use for StreamScaler", | ||
doc="""Property parameter object used to define property | ||
calculations, **default** - useDefault. | ||
**Valid values:** { | ||
**useDefault** - use default package from parent model or flowsheet, | ||
**PropertyParameterObject** - a PropertyParameterBlock object.}""", | ||
), | ||
) | ||
CONFIG.declare( | ||
"property_package_args", | ||
ConfigBlock( | ||
implicit=True, | ||
description="Arguments to use for constructing property packages", | ||
doc="""A ConfigBlock with arguments to be passed to a property | ||
block(s) and used when constructing these, | ||
**default** - None. | ||
**Valid values:** { | ||
see property package for documentation.}""", | ||
), | ||
) | ||
|
||
def build(self): | ||
""" | ||
General build method for StreamScalerData. This method calls a number | ||
of sub-methods which automate the construction of expected attributes | ||
of unit models. | ||
Inheriting models should call `super().build`. | ||
Args: | ||
None | ||
Returns: | ||
None | ||
""" | ||
# Call super.build() | ||
super(StreamScalerData, self).build() | ||
|
||
tmp_dict = dict(**self.config.property_package_args) | ||
tmp_dict["has_phase_equilibrium"] = False | ||
tmp_dict["defined_state"] = True | ||
|
||
# Call setup methods from ControlVolumeBlockData | ||
self._get_property_package() | ||
self._get_indexing_sets() | ||
|
||
self.properties = self.config.property_package.build_state_block( | ||
self.flowsheet().time, doc="Material properties at inlet", **tmp_dict | ||
) | ||
self.scaled_expressions = Block() | ||
self.multiplier = Var( | ||
initialize=1, | ||
domain=PositiveReals, | ||
units=pyunits.dimensionless, | ||
doc="Factor by which to scale dimensionless streams", | ||
) | ||
self.add_inlet_port(name="inlet", block=self.properties) | ||
self.outlet = Port(doc="Outlet port") | ||
|
||
def rule_scale_var(b, *args, var=None): | ||
return self.multiplier * var[args] | ||
|
||
def rule_no_scale_var(b, *args, var=None): | ||
return var[args] | ||
|
||
for var_name in self.inlet.vars.keys(): | ||
var = getattr(self.inlet, var_name) | ||
if "flow" in var_name: | ||
rule = partial(rule_scale_var, var=var) | ||
else: | ||
rule = partial(rule_no_scale_var, var=var) | ||
self.scaled_expressions.add_component( | ||
var_name, VarLikeExpression(var.index_set(), rule=rule) | ||
) | ||
expr = getattr(self.scaled_expressions, var_name) | ||
self.outlet.add(expr, var_name) | ||
|
||
def initialize_build( | ||
blk, outlvl=idaeslog.NOTSET, optarg=None, solver=None, hold_state=False | ||
): | ||
""" | ||
Initialization routine for StreamScaler. | ||
Keyword Arguments: | ||
outlvl : sets output level of initialization routine | ||
optarg : solver options dictionary object (default=None, use | ||
default solver options) | ||
solver : str indicating which solver to use during | ||
initialization (default = None, use default solver) | ||
hold_state : flag indicating whether the initialization routine | ||
should unfix any state variables fixed during | ||
initialization, **default** - False. **Valid values:** | ||
**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. | ||
Returns: | ||
If hold_states is True, returns a dict containing flags for which | ||
states were fixed during initialization. | ||
""" | ||
|
||
# Create solver | ||
|
||
# Initialize inlet state blocks | ||
flags = blk.properties.initialize( | ||
outlvl=outlvl, | ||
optarg=optarg, | ||
solver=solver, | ||
hold_state=True, | ||
) | ||
|
||
if hold_state is True: | ||
return flags | ||
else: | ||
blk.release_state(flags, outlvl=outlvl) | ||
|
||
def release_state(blk, flags, outlvl=idaeslog.NOTSET): | ||
""" | ||
Method to release state variables fixed during initialization. | ||
Keyword Arguments: | ||
flags : dict containing information of which state variables | ||
were fixed during initialization, and should now be | ||
unfixed. This dict is returned by initialize if | ||
hold_state = True. | ||
outlvl : sets output level of logging | ||
Returns: | ||
None | ||
""" | ||
blk.properties.release_state(flags, outlvl=outlvl) | ||
|
||
def _get_stream_table_contents(self, time_point=0): | ||
io_dict = { | ||
"Inlet": self.inlet, | ||
# "Outlet": self.outlet, | ||
} | ||
return create_stream_table_dataframe(io_dict, time_point=time_point) | ||
|
||
def calculate_scaling_factors(self): | ||
# Scaling factors for the property block are calculated automatically | ||
super().calculate_scaling_factors() | ||
|
||
# Need to pass on scaling factors from the property block to the outlet | ||
# VarLikeExpressions so arcs get scaled right | ||
if self.multiplier.value == 0: | ||
default = 1 | ||
else: | ||
default = 1 / self.multiplier.value | ||
|
||
scale = iscale.get_scaling_factor( | ||
self.multiplier, default=default, warning=False | ||
) | ||
for var_name in self.inlet.vars.keys(): | ||
var = getattr(self.inlet, var_name) | ||
outlet_expr = getattr(self.outlet, var_name) | ||
for key, subvar in var.items(): | ||
sf = iscale.get_scaling_factor(subvar, default=1, warning=True) | ||
iscale.set_scaling_factor(outlet_expr[key], scale * sf) |
Oops, something went wrong.