Source code for idaes.core.util.initialization

# -*- coding: UTF-8 -*-
##############################################################################
# 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 initialization of IDAES models.
"""

from pyomo.environ import Block, Var
from pyomo.network import Arc

from idaes.core.util.exceptions import ConfigurationError

__author__ = "Andrew Lee, John Siirola"


[docs]def fix_state_vars(blk, state_args={}): """ Method for fixing state variables within StateBlocks. Method takes an optional argument of values to use when fixing variables. Args: blk : An IDAES StateBlock object in which to fix the state variables state_args : a dict containing values to use when fixing state variables. Keys must match with names used in the define_state_vars method, and indices of any variables must agree. Returns: A dict keyed by block index, state variable name (as defined by define_state_variables) and variable index indicating the fixed status of each variable before the fix_state_vars method was applied. """ flags = {} for k in blk.keys(): for n, v in blk[k].define_state_vars().items(): for i in v: flags[k, n, i] = v[i].is_fixed() # If not fixed, fix at either guess provided or current value if not v[i].is_fixed(): if n in state_args: # Try to get initial guess from state_args try: if i is None: val = state_args[n] else: val = state_args[n][i] except KeyError: raise ConfigurationError( 'Indexes in state_args did not agree with ' 'those of state variable {}. Please ensure ' 'that indexes for initial guesses are correct.' .format(n)) v[i].fix(val) else: # No guess, try to use current value if v[i].value is not None: v[i].fix() else: # No initial value - raise Exception before this # gets to a solver. raise ConfigurationError( 'State variable {} does not have a value ' 'assigned. This usually occurs when a Var ' 'is not assigned an initial value when it is ' 'created. Please ensure all variables have ' 'valid values before fixing them.' .format(v.name)) return flags
[docs]def revert_state_vars(blk, flags): """ Method to revert the fixed state of the state variables within an IDAES StateBlock based on a set of flags of the previous state. Args: blk : an IDAES StateBlock flags : a dict of bools indicating previous state with keys in the form (StateBlock index, state variable name (as defined by define_state_vars), var indices). Returns: None """ for k in blk.keys(): for n, v in blk[k].define_state_vars().items(): for i in v: try: if not flags[k, n, i]: v[i].unfix() except KeyError: raise ConfigurationError( 'Indices of flags proved do not match with indices of' 'the StateBlock. Please make sure you are using the ' 'correct StateBlock.')
[docs]def propagate_state(stream, direction="forward"): """ This method propagates values between Ports along Arcs. Values can be propagated in either direction using the direction argument. Args: stream : Arc object along which to propagate values direction: direction in which to propagate values. Default = 'forward' Valid value: 'forward', 'backward'. Returns: None """ if not isinstance(stream, Arc): raise TypeError("Unexpected type of stream argument. Value must be " "a Pyomo Arc.") if direction == "forward": value_source = stream.source value_dest = stream.destination elif direction == "backward": value_source = stream.destination value_dest = stream.source else: raise ValueError("Unexpected value for direction argument: ({}). " "Value must be either 'forward' or 'backward'." .format(direction)) for v in value_source.vars: for i in value_source.vars[v]: if not isinstance(value_dest.vars[v], Var): raise TypeError("Port contains one or more members which are " "not Vars. propogate_state works by assigning " "to the value attribute, thus can only be " "when Port members are Pyomo Vars.") if not value_dest.vars[v][i].fixed: value_dest.vars[v][i].value = value_source.vars[v][i].value
# HACK, courtesy of J. Siirola
[docs]def solve_indexed_blocks(solver, blocks, **kwds): """ This method allows for solving of Indexed Block components as if they were a single Block. A temporary Block object is created which is populated with the contents of the objects in the blocks argument and then solved. Args: solver : a Pyomo solver object to use when solving the Indexed Block blocks : an object which inherits from Block, or a list of Blocks kwds : a dict of argumnets to be passed to the solver Returns: A Pyomo solver results object """ # Check blocks argument, and convert to a list of Blocks if isinstance(blocks, Block): blocks = [blocks] try: # Create a temporary Block tmp = Block(concrete=True) nBlocks = len(blocks) # Iterate over indexed objects for i, b in enumerate(blocks): # Check that object is a Block if not isinstance(b, Block): raise TypeError("Trying to apply solve_indexed_blocks to " "object containing non-Block objects") # Append components of BlockData to temporary Block try: tmp._decl["block_%s" % i] = i tmp._decl_order.append((b, i+1 if i < nBlocks-1 else None)) except Exception: raise Exception("solve_indexed_blocks method failed adding " "components to temporary block.") # Set ctypes on temporary Block tmp._ctypes[Block] = [0, nBlocks-1, nBlocks] # Solve temporary Block results = solver.solve(tmp, **kwds) finally: # Clean up temporary Block contents so they are not removed when Block # is garbage collected. tmp._decl = {} tmp._decl_order = [] tmp._ctypes = {} # Return results return results