##############################################################################
# Institute for the Design of Advanced Energy Systems Process Systems
# Engineering Framework (IDAES PSE Framework) Copyright (c) 2018, 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".
##############################################################################
from idaes.core import Stream
from pyomo.environ import *
from pyomo.core.expr.current import identify_variables
from pyomo.core.kernel.component_set import ComponentSet
#from pyomo.core.base import Transformation, Constraint, \
# ConstraintList, Var, VarList, TraversalStrategy
from pyomo.network.port import _PortData, SimplePort
[docs]def large_residuals(blk, tol=1e-5):
"""
Generator return active Pyomo constraints with residuals greater than tol.
Args:
blk: a Pyomo block in which to look for constraints
tol: show constraints with residuals greated than tol
"""
for o in blk.component_objects(Constraint, descend_into=True):
for i, c in o.iteritems():
if c.active and value(c.lower - c.body()) > tol:
yield c
elif c.active and value(c.body() - c.upper) > tol:
yield c
[docs]def fixed_variables(blk):
"""
Generator returning fixed variables in a model.
Args:
blk: a Pyomo block in which to look for variables.
"""
for o in blk.component_data_objects(Var):
if o.fixed: yield o
[docs]def unfixed_variables(blk):
"""
Generator returning free variables in a model.
Args:
blk: a Pyomo block in which to look for variables.
"""
for o in blk.component_data_objects(Var):
if not o.fixed: yield item
[docs]def free_variables(blk):
"""
Generator returning free variables in a model. same as unfixed
Args:
blk: a Pyomo block in which to look for variables.
"""
for o in blk.component_data_objects(Var):
if not o.fixed: yield o
[docs]def stale_variables(blk):
"""
Generator returning stale variables in a model.
Args:
blk: a Pyomo block in which to look for variables.
"""
for o in blk.component_data_objects(Var):
if not o.fixed and o.stale: yield o
[docs]def active_equalities(blk):
"""
Generator returning active equality constraints in a model.
Args:
blk: a Pyomo block in which to look for variables.
"""
for o in blk.component_data_objects(Constraint, active=True):
if o.upper == o.lower: yield o
[docs]def count_free_variables(blk):
"""
Count free variables that are in active equality constraints. Ignore
inequalities, because this is used in the degrees of freedom calculations
"""
return len(free_variables_in_active_equalities_set(blk))
[docs]def count_equality_constraints(blk):
"""
Count active equality constraints.
"""
return len(active_equality_set(blk))
[docs]def degrees_of_freedom(blk):
"""
Return the degrees of freedom.
"""
return count_free_variables(blk) - count_equality_constraints(blk)
[docs]def active_equality_set(blk):
"""
Generator returning active equality constraints in a model.
Args:
blk: a Pyomo block in which to look for variables.
"""
ac = ComponentSet()
for c in active_equalities(blk):
ac.add(c)
return ac
[docs]def variables_in_active_equalities_set(blk):
"""
Return a set of variables that are contined in active equalities.
"""
vin = ComponentSet()
for c in active_equalities(blk):
for v in identify_variables(c.body):
vin.add(v)
return vin
[docs]def free_variables_in_active_equalities_set(blk):
"""
Return a set of variables that are contined in active equalities.
"""
vin = ComponentSet()
for c in active_equalities(blk):
for v in identify_variables(c.body):
if not v.fixed: vin.add(v)
return vin
[docs]def connections(blk):
"""
Returns a list of connected blocks at the level under blk, this only goes
one level deep, used for displaying a flowsheet.
"""
cblks = ComponentSet() # blocks that are children of blk
connected_blocks = []
for b in blk.component_objects(Block, descend_into=False):
if isinstance(b, Stream):
for i in b:
connected_blocks.append(
[b[i].config.source, b[i].config.destination])
else:
cblks.add(b)
for c in connected_blocks:
for i in (0,1):
if c[i] in cblks:
continue
visited = [c[i]]
b = c[i]
while True:
if b.parent_component() == b:
b = b.parent_block()
else:
b = b.parent_component()
if(b in visited): # check circular case just to be safe
c[i] = None
break
elif b in cblks: # found a block at the level of interest
c[i] = b
break
elif b is None: # is outside blk
c[i] = None
break
visited.append(b)
# Should have connected blocks at the level we are interested in now
# eliminate None and duplicates.
idd = {}
ids = set()
for c in connected_blocks:
if c[0] is None or c[1] is None:
continue
id0 = id(c[0])
id1 = id(c[1])
ids.add((id0, id1))
idd[id0] = c[0]
idd[id1] = c[1]
connected_blocks = []
skip = set()
for c in ids:
if c in skip:
continue
elif c[0] == c[1]:
continue
two_way = (c[1], c[0]) in ids
if two_way:
skip.add((c[1], c[0]))
connected_blocks.append((idd[c[0]], idd[c[1]], two_way))
return connected_blocks