##############################################################################
# Institute for the Design of Advanced Energy Systems Process Systems
# Engineering Framework (IDAES PSE Framework) Copyright (c) 2018-2019, 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.txt and LICENSE.txt for full copyright and
# license information, respectively. Both files are also available online
# at the URL "https://github.com/IDAES/idaes-pse".
##############################################################################
"""
This module contains utility functions for use in testing IDAES models.
"""
__author__ = "Andrew Lee"
from pyomo.environ import Set, SolverFactory, Var
from pyomo.common.config import ConfigBlock
from idaes.core import (declare_process_block_class,
PhysicalParameterBlock,
StateBlock,
StateBlockData,
ReactionParameterBlock,
ReactionBlockBase,
ReactionBlockDataBase,
MaterialFlowBasis)
[docs]def get_default_solver():
"""
Tries to set-up the default solver for testing, and returns None if not
available
"""
if SolverFactory('ipopt').available(exception_flag=False):
solver = SolverFactory('ipopt')
solver.options = {'tol': 1e-6}
else:
solver = None
return solver
# -----------------------------------------------------------------------------
# Define some generic PhysicalBlock and ReactionBlock classes for testing
@declare_process_block_class("PhysicalParameterTestBlock")
class _PhysicalParameterBlock(PhysicalParameterBlock):
def build(self):
super(_PhysicalParameterBlock, self).build()
self.phase_list = Set(initialize=["p1", "p2"])
self.component_list = Set(initialize=["c1", "c2"])
self.phase_equilibrium_idx = Set(initialize=["e1", "e2"])
self.element_list = Set(initialize=["H", "He", "Li"])
self.element_comp = {"c1": {"H": 1, "He": 2, "Li": 3},
"c2": {"H": 4, "He": 5, "Li": 6}}
self.phase_equilibrium_list = \
{"e1": ["c1", ("p1", "p2")],
"e2": ["c2", ("p1", "p2")]}
# Attribute to switch flow basis for testing
self.basis_switch = 1
self.state_block_class = TestStateBlock
@classmethod
def define_metadata(cls, obj):
obj.add_default_units({'time': 's',
'length': 'm',
'mass': 'g',
'amount': 'mol',
'temperature': 'K',
'energy': 'J',
'holdup': 'mol'})
[docs]class SBlockBase(StateBlock):
[docs] def initialize(blk, outlvl=0, optarg=None, solver=None,
hold_state=False, **state_args):
for k in blk.keys():
blk[k].init_test = True
blk[k].hold_state = hold_state
def release_state(blk, flags=None, outlvl=0):
for k in blk.keys():
blk[k].hold_state = not blk[k].hold_state
[docs]@declare_process_block_class("TestStateBlock", block_class=SBlockBase)
class StateTestBlockData(StateBlockData):
CONFIG = ConfigBlock(implicit=True)
[docs] def build(self):
super(StateTestBlockData, self).build()
self.test_var = Var(initialize=1)
self.pressure = Var(initialize=1e5)
self.temperature = Var(initialize=300)
self.gibbs_mol_phase_comp = Var(self._params.phase_list,
self._params.component_list,
initialize=50)
[docs] def get_material_flow_terms(b, p, j):
return b.test_var
[docs] def get_material_density_terms(b, p, j):
return b.test_var
[docs] def get_enthalpy_flow_terms(b, p):
return b.test_var
[docs] def get_enthalpy_density_terms(b, p):
return b.test_var
def model_check(self):
self.check = True
[docs] def get_material_flow_basis(b):
if b.config.parameters.basis_switch == 1:
return MaterialFlowBasis.molar
elif b.config.parameters.basis_switch == 2:
return MaterialFlowBasis.mass
else:
return MaterialFlowBasis.other
[docs] def define_state_vars(self):
return {"temperature": self.temperature,
"pressure": self.pressure}
@declare_process_block_class("ReactionParameterTestBlock")
class _ReactionParameterBlock(ReactionParameterBlock):
def build(self):
super(_ReactionParameterBlock, self).build()
self.phase_list = Set(initialize=["p1", "p2"])
self.component_list = Set(initialize=["c1", "c2"])
self.rate_reaction_idx = Set(initialize=["r1", "r2"])
self.equilibrium_reaction_idx = Set(initialize=["e1", "e2"])
self.rate_reaction_stoichiometry = {("r1", "p1", "c1"): 1,
("r1", "p1", "c2"): 1,
("r1", "p2", "c1"): 1,
("r1", "p2", "c2"): 1,
("r2", "p1", "c1"): 1,
("r2", "p1", "c2"): 1,
("r2", "p2", "c1"): 1,
("r2", "p2", "c2"): 1}
self.equilibrium_reaction_stoichiometry = {
("e1", "p1", "c1"): 1,
("e1", "p1", "c2"): 1,
("e1", "p2", "c1"): 1,
("e1", "p2", "c2"): 1,
("e2", "p1", "c1"): 1,
("e2", "p1", "c2"): 1,
("e2", "p2", "c1"): 1,
("e2", "p2", "c2"): 1}
self.reaction_block_class = ReactionBlock
# Attribute to switch flow basis for testing
self.basis_switch = 1
@classmethod
def define_metadata(cls, obj):
obj.add_default_units({'time': 's',
'length': 'm',
'mass': 'g',
'amount': 'mol',
'temperature': 'K',
'energy': 'J',
'holdup': 'mol'})
@classmethod
def get_required_properties(self):
return {}
[docs]class RBlockBase(ReactionBlockBase):
[docs] def initialize(blk, outlvl=0, optarg=None, solver=None):
for k in blk.keys():
blk[k].init_test = True
[docs]@declare_process_block_class("ReactionBlock", block_class=RBlockBase)
class ReactionBlockData(ReactionBlockDataBase):
CONFIG = ConfigBlock(implicit=True)
[docs] def build(self):
super(ReactionBlockData, self).build()
self.reaction_rate = Var(["r1", "r2"])
self.dh_rxn = {"r1": 10,
"r2": 20,
"e1": 30,
"e2": 40}
def model_check(self):
self.check = True
[docs] def get_reaction_rate_basis(b):
if b.config.parameters.basis_switch == 1:
return MaterialFlowBasis.molar
elif b.config.parameters.basis_switch == 2:
return MaterialFlowBasis.mass
else:
return MaterialFlowBasis.other