###############################################################################
# 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-2024 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.
###############################################################################

from enum import Enum
import pandas as pd
import numpy as np

import pyomo.environ as pyo
from pyomo.common.collections import ComponentSet, ComponentMap
from pyomo.util.calc_var_value import calculate_variable_from_constraint

import idaes.core.util.scaling as iscale
from pyomo.dae import DerivativeVar
from idaes.core.solvers import petsc
import idaes.logger as idaeslog
import idaes.core.util.model_serializer as ms
from idaes_examples.mod.power_gen.soc_dynamic_flowsheet import SocStandaloneFlowsheet as SocFlowsheet
import matplotlib.pyplot as plt
from idaes.models.control.controller import ControllerType, ControllerMVBoundType, ControllerAntiwindupType
from IPython.display import SVG, display

SOC Flowsheet — PID Control#

Author: Douglas Allan

Maintainer: Douglas Allan

Updated: 2024-26-03

1. Introduction#

This example is designed to demonstrate the use of PI controllers in a complex flowsheet to simulate ramping between different, predetermined setpoints. Steady-state optimization to obtain these setpoints is the subject of a future example.

2. Model Description#

The underlying flowsheet consists of a solid oxide cell (SOC) and supporting equipment consisting of electric trim heaters, heat exchangers, a blower for sweep air input, and a condenser to remove excess water from a hydrogen-rich stream. The flowsheet is sized appropriately to produce about 2 kg/s of hydrogen when at its current density limit. Power production mode is then sized to be whatever the net power production is at an average of 400 \(\text{mA}/\text{cm}^2\). The trim heaters and heat exchangers are modeled in considerable detail in order to accurately gauge the thermal capacitance of the system. The condenser, on the other hand, is modeled as having perfect control to keep its output temperature at \(45^\circ C\). The steam source (presumably an electric boiler) and hydrogen compression train (which would include additional condensers/water traps) are not modeled.

The OperatingScenario Enum allows the user to select which initial condition to use. The functions are helper functions for later.

class OperatingScenario(Enum):
    maximum_production = 1
    power_mode = 2

def scale_indexed_constraint(con, sf):
    for idx, c in con.items():
        iscale.constraint_scaling_transform(c, sf)

def set_indexed_variable_bounds(var, bounds):
    for idx, subvar in var.items():
        subvar.bounds = bounds

def create_ramping_eqns(fs, vars, time_scaling_factor=1):
    def rule_ramp(b, t, dvdt, v_ramp):
        return dvdt[t] == v_ramp[t]
    t0 = fs.time.first()

    for var in vars:
        var.unfix()
        shortname = var.name.split(".")[-1]
        blk = var.parent_block()
        dvdt = DerivativeVar(var, wrt=fs.time, initialize=0)
        setattr(blk, "d" + shortname + "dt", dvdt)
        v_ramp = pyo.Var(fs.time, initialize=0)
        setattr(blk, shortname + "_ramp_rate", v_ramp)
        v_ramp_eqn = pyo.Constraint(fs.time, rule=lambda b, t: rule_ramp(b, t, dvdt, v_ramp))
        setattr(blk, shortname + "_ramp_rate_eqn", v_ramp_eqn)
        for t in fs.time:
            sv = iscale.get_scaling_factor(var[t], default=1)
            iscale.set_scaling_factor(dvdt[t], sv/time_scaling_factor)
            iscale.set_scaling_factor(v_ramp[t], sv/time_scaling_factor)
            iscale.constraint_scaling_transform(v_ramp_eqn[t], sv/time_scaling_factor)

        v_ramp_eqn[t0].deactivate()
        v_ramp[t0].fix(0)

We begin by ramping from the maximum H2 production setpoint to maximum power production. The ramp starts at one hour, the ramp lasts five minutes, the system is allowed to settle at maximum power mode for two hours, there is another five minute ramp back to maximum H2 production, then the system is given three hours to settle at the end.

operating_scenario = OperatingScenario.maximum_production
m = pyo.ConcreteModel()
t_start = 1 * 60 * 60
t_ramp = 5 * 60
t_settle = 2 * 60 * 60
t_end = 3 * 60 * 60

dt_set = [t_start, t_ramp, t_settle, t_ramp, t_end]

time_set = [sum(dt_set[:j]) for j in range(len(dt_set)+1)]

# The names here correspond to the row names in 
# soec_flowsheet_operating_conditions.csv
# There should be len(time_set) entries here.
# We start simulating a period at maximum production
# in order to confirm the system is at steady state.
if operating_scenario == OperatingScenario.maximum_production:
    setpoints = [
        "maximum_H2", "maximum_H2",
        "power", "power",
        "maximum_H2", "maximum_H2",
    ]
elif operating_scenario == OperatingScenario.power_mode: 
    setpoints = [
        "power", "power",
        "maximum_H2", "maximum_H2",
        "power", "power",
    ]
else:
    raise RuntimeError("Please choose a valid operating scenario")

m.fs = SocFlowsheet(
    dynamic=True,
    time_set=time_set,
    time_units=pyo.units.s,
    thin_electrolyte_and_oxygen_electrode=True,
    include_interconnect=True,
)
scaling_log = idaeslog.getLogger("idaes.core.util.scaling")
scaling_log.setLevel(idaeslog.ERROR)
iscale.calculate_scaling_factors(m)
2024-05-09 18:34:27 [ERROR] idaes.core.base.process_block: Failure in build: fs.water_prop_params
Traceback (most recent call last):
  File "/home/docs/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/idaes/core/base/process_block.py", line 41, in _rule_default
    b.build()
  File "/home/docs/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/idaes/models/properties/general_helmholtz/helmholtz_functions.py", line 1441, in build
    raise RuntimeError("Helmholtz EoS external functions not available")
RuntimeError: Helmholtz EoS external functions not available
ERROR: Constructing component 'fs.water_prop_params' from data=None failed:
        RuntimeError: Helmholtz EoS external functions not available
2024-05-09 18:34:27 [ERROR] idaes.core.base.process_block: Failure in build: fs
Traceback (most recent call last):
  File "/home/docs/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/idaes/core/base/process_block.py", line 41, in _rule_default
    b.build()
  File "/home/docs/checkouts/readthedocs.org/user_builds/idaes-examples/checkouts/latest/idaes_examples/mod/power_gen/soc_dynamic_flowsheet.py", line 97, in build
    self._add_properties()
  File "/home/docs/checkouts/readthedocs.org/user_builds/idaes-examples/checkouts/latest/idaes_examples/mod/power_gen/soc_dynamic_flowsheet.py", line 123, in _add_properties
    self.water_prop_params = iapws95.Iapws95ParameterBlock()
  File "/home/docs/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/pyomo/core/base/block.py", line 571, in __setattr__
    self.add_component(name, val)
  File "/home/docs/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/pyomo/core/base/block.py", line 1129, in add_component
    val.construct(data)
  File "/home/docs/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/pyomo/core/base/block.py", line 2186, in construct
    self._getitem_when_not_present(_idx)
  File "/home/docs/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/pyomo/core/base/block.py", line 2101, in _getitem_when_not_present
    obj = self._rule(_block, idx)
  File "/home/docs/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/pyomo/core/base/initializer.py", line 316, in __call__
    return self._fcn(parent, idx)
  File "/home/docs/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/idaes/core/base/process_block.py", line 41, in _rule_default
    b.build()
  File "/home/docs/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/idaes/models/properties/general_helmholtz/helmholtz_functions.py", line 1441, in build
    raise RuntimeError("Helmholtz EoS external functions not available")
RuntimeError: Helmholtz EoS external functions not available
ERROR: Constructing component 'fs' from data=None failed:
        RuntimeError: Helmholtz EoS external functions not available
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
Cell In[3], line 32
     29 else:
     30     raise RuntimeError("Please choose a valid operating scenario")
---> 32 m.fs = SocFlowsheet(
     33     dynamic=True,
     34     time_set=time_set,
     35     time_units=pyo.units.s,
     36     thin_electrolyte_and_oxygen_electrode=True,
     37     include_interconnect=True,
     38 )
     39 scaling_log = idaeslog.getLogger("idaes.core.util.scaling")
     40 scaling_log.setLevel(idaeslog.ERROR)

File ~/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/pyomo/core/base/block.py:571, in BlockData.__setattr__(self, name, val)
    566 if name not in self.__dict__:
    567     if isinstance(val, Component):
    568         #
    569         # Pyomo components are added with the add_component method.
    570         #
--> 571         self.add_component(name, val)
    572     else:
    573         #
    574         # Other Python objects are added with the standard __setattr__
    575         # method.
    576         #
    577         super(BlockData, self).__setattr__(name, val)

File ~/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/pyomo/core/base/block.py:1129, in BlockData.add_component(self, name, val)
   1121     logger.debug(
   1122         "Constructing %s '%s' on %s from data=%s",
   1123         val.__class__.__name__,
   (...)
   1126         str(data),
   1127     )
   1128 try:
-> 1129     val.construct(data)
   1130 except:
   1131     err = sys.exc_info()[1]

File ~/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/pyomo/core/base/block.py:2186, in Block.construct(self, data)
   2184                     obj.construct(data.get(name, None))
   2185         # Trigger the (normal) initialization of the block
-> 2186         self._getitem_when_not_present(_idx)
   2187 finally:
   2188     # We must allow that id(self) may no longer be in
   2189     # _BlockConstruction.data, as _getitem_when_not_present will
   2190     # have already removed the entry for scalar blocks (as the
   2191     # BlockData and the Block component are the same object)
   2192     if data is not None:

File ~/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/pyomo/core/base/block.py:2101, in Block._getitem_when_not_present(self, idx)
   2098     data = None
   2100 try:
-> 2101     obj = self._rule(_block, idx)
   2102     # If the user returns a block, transfer over everything
   2103     # they defined into the empty one we created.  We do
   2104     # this inside the try block so that any abstract
   2105     # components declared by the rule have the opportunity
   2106     # to be initialized with data from
   2107     # _BlockConstruction.data as they are transferred over.
   2108     if obj is not _block and isinstance(obj, BlockData):

File ~/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/pyomo/core/base/initializer.py:316, in IndexedCallInitializer.__call__(self, parent, idx)
    314     return self._fcn(parent, *idx)
    315 else:
--> 316     return self._fcn(parent, idx)

File ~/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/idaes/core/base/process_block.py:41, in _rule_default(b, *args)
     35 """
     36 Default rule for ProcessBlock, which calls build(). A different rule can
     37 be specified to add additional build steps, or to not call build at all
     38 using the normal rule argument to ProcessBlock init.
     39 """
     40 try:
---> 41     b.build()
     42 except Exception:
     43     logging.getLogger(__name__).exception(f"Failure in build: {b}")

File ~/checkouts/readthedocs.org/user_builds/idaes-examples/checkouts/latest/idaes_examples/mod/power_gen/soc_dynamic_flowsheet.py:97, in SocStandaloneFlowsheetData.build(self)
     94 def build(self):
     95     super().build()
---> 97     self._add_properties()
     98     self._add_units()
     99     self._add_arcs()

File ~/checkouts/readthedocs.org/user_builds/idaes-examples/checkouts/latest/idaes_examples/mod/power_gen/soc_dynamic_flowsheet.py:123, in SocStandaloneFlowsheetData._add_properties(self)
    122 def _add_properties(self):
--> 123     self.water_prop_params = iapws95.Iapws95ParameterBlock()
    124     self.o2_side_prop_params = GenericParameterBlock(
    125         **get_prop(self.sweep_comp, ["Vap"], eos=EosType.IDEAL),
    126         doc="Air property parameters",
    127     )
    128     self.h2_side_prop_params = GenericParameterBlock(
    129         **get_prop(["H2", "H2O", "Ar", "N2"], ["Vap"], eos=EosType.IDEAL),
    130         doc="H2O + H2 gas property parameters",
    131     )

File ~/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/pyomo/core/base/block.py:571, in BlockData.__setattr__(self, name, val)
    566 if name not in self.__dict__:
    567     if isinstance(val, Component):
    568         #
    569         # Pyomo components are added with the add_component method.
    570         #
--> 571         self.add_component(name, val)
    572     else:
    573         #
    574         # Other Python objects are added with the standard __setattr__
    575         # method.
    576         #
    577         super(BlockData, self).__setattr__(name, val)

File ~/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/pyomo/core/base/block.py:1129, in BlockData.add_component(self, name, val)
   1121     logger.debug(
   1122         "Constructing %s '%s' on %s from data=%s",
   1123         val.__class__.__name__,
   (...)
   1126         str(data),
   1127     )
   1128 try:
-> 1129     val.construct(data)
   1130 except:
   1131     err = sys.exc_info()[1]

File ~/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/pyomo/core/base/block.py:2186, in Block.construct(self, data)
   2184                     obj.construct(data.get(name, None))
   2185         # Trigger the (normal) initialization of the block
-> 2186         self._getitem_when_not_present(_idx)
   2187 finally:
   2188     # We must allow that id(self) may no longer be in
   2189     # _BlockConstruction.data, as _getitem_when_not_present will
   2190     # have already removed the entry for scalar blocks (as the
   2191     # BlockData and the Block component are the same object)
   2192     if data is not None:

File ~/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/pyomo/core/base/block.py:2101, in Block._getitem_when_not_present(self, idx)
   2098     data = None
   2100 try:
-> 2101     obj = self._rule(_block, idx)
   2102     # If the user returns a block, transfer over everything
   2103     # they defined into the empty one we created.  We do
   2104     # this inside the try block so that any abstract
   2105     # components declared by the rule have the opportunity
   2106     # to be initialized with data from
   2107     # _BlockConstruction.data as they are transferred over.
   2108     if obj is not _block and isinstance(obj, BlockData):

File ~/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/pyomo/core/base/initializer.py:316, in IndexedCallInitializer.__call__(self, parent, idx)
    314     return self._fcn(parent, *idx)
    315 else:
--> 316     return self._fcn(parent, idx)

File ~/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/idaes/core/base/process_block.py:41, in _rule_default(b, *args)
     35 """
     36 Default rule for ProcessBlock, which calls build(). A different rule can
     37 be specified to add additional build steps, or to not call build at all
     38 using the normal rule argument to ProcessBlock init.
     39 """
     40 try:
---> 41     b.build()
     42 except Exception:
     43     logging.getLogger(__name__).exception(f"Failure in build: {b}")

File ~/checkouts/readthedocs.org/user_builds/idaes-examples/envs/latest/lib/python3.8/site-packages/idaes/models/properties/general_helmholtz/helmholtz_functions.py:1441, in HelmholtzParameterBlockData.build(self)
   1439 """Populate the parameter block"""
   1440 if not self.available():
-> 1441     raise RuntimeError("Helmholtz EoS external functions not available")
   1442 super().build()
   1443 # Check if the specified component is supported

RuntimeError: Helmholtz EoS external functions not available

Interior point solvers like IPOPT have difficulties when unconstrained solutions occur too close to variable bounds. We therefore strip bounds from some variables that previous simulations have shown to be causing problems.

for t in m.fs.time:
    m.fs.condenser_flash.control_volume.properties_in[t].flow_mol_phase["Liq"].domain = pyo.Reals
    m.fs.condenser_flash.control_volume.properties_in[t].flow_mol_phase["Liq"].bounds = (None, None)
    m.fs.condenser_flash.control_volume.properties_in[t].phase_frac["Liq"].domain = pyo.Reals
    m.fs.condenser_flash.control_volume.properties_in[t].phase_frac["Liq"].bounds = (None, None)
    for var in [
        m.fs.condenser_flash.control_volume.properties_in[t].log_mole_frac_tdew, 
        m.fs.condenser_flash.control_volume.properties_in[t]._mole_frac_tdew,
    ]:
        for idx in var.index_set():
            var[idx].domain = pyo.Reals
            var[idx].bounds = (None, None)

3. Process Control#

Now we add controllers to the flowsheet. The flowsheet has a helper function, add_controllers that adds the controllers if passed a ComponentMap that maps manipulated variables (MVs) to tuples that specify the controller. The tuple contains the controller name, the corresponding controlled variable (CV), the type of controller used, the way the controller handles MV bounds, and the antiwindup method.

We restrict ourselves to using P and PI controllers, because derivative action is severely degraded by noise, but PETSc cannot incorporate noise into its simulations.

Controllers can either have no bounds with the NONE option (which may result in use of unphysical controls), the SMOOTH_BOUND option which uses smooth max and min functions in order to keep the MV within certain thresholds, and the LOGISTIC option, which uses a logistic function to keep the MV within bounds. The LOGISTIC option is a worse representation of an actual thresholding function than SMOOTH_BOUND but may be easier for integrators to handle.

When both variable bounds and integral action are present, integral windup is a problem. If one uses the NONE option, no antiwindup is used. If one uses the CONDITIONAL_INTEGRATION method, setpoint error does not integrate when the system is at its bounds. This method is relatively easy to implement but the transition between integrating and not integrating causes integrators to slow down significantly. The BACK_CALCULATION method subtracts an amount proportional to the difference between the current MV value and the value that the controller would use without variable bounds from the integrated error. This method gives better performance (and is much easier to integrate) than CONDITIONAL_INTEGRATION, but it requires a back calculation gain term to be chosen.

antiwindup = ControllerAntiwindupType.BACK_CALCULATION
inner_controller_pairs = ComponentMap()
inner_controller_pairs[m.fs.feed_heater.electric_heat_duty] = (
    "feed_heater_inner_controller",
    m.fs.soc_module.fuel_inlet.temperature,
    ControllerType.PI,
    ControllerMVBoundType.SMOOTH_BOUND,
    antiwindup,
)
inner_controller_pairs[m.fs.sweep_heater.electric_heat_duty] = (
    "sweep_heater_inner_controller",
    m.fs.soc_module.oxygen_inlet.temperature,
    ControllerType.PI,
    ControllerMVBoundType.SMOOTH_BOUND,
    antiwindup,
)
m.fs.add_controllers(inner_controller_pairs)

variable_pairs = ComponentMap()
variable_pairs[m.fs.feed_heater_inner_controller.setpoint] = (
    "feed_heater_outer_controller",
    m.fs.soc_module.fuel_outlet.temperature,
    ControllerType.P,
    ControllerMVBoundType.NONE,
    ControllerAntiwindupType.NONE,
)
variable_pairs[m.fs.sweep_heater_inner_controller.setpoint] = (
    "sweep_heater_outer_controller",
    m.fs.soc_module.oxygen_outlet.temperature,
    ControllerType.P,
    ControllerMVBoundType.NONE,
    ControllerAntiwindupType.NONE,
)
variable_pairs[m.fs.soc_module.potential_cell] = (
    "voltage_controller",
    m.fs.soc_module.fuel_outlet_mole_frac_comp_H2,
    ControllerType.PI,
    ControllerMVBoundType.SMOOTH_BOUND,
    antiwindup,
)
variable_pairs[m.fs.sweep_blower.inlet.flow_mol] = (
    "sweep_blower_controller",
    m.fs.stack_core_temperature,
    ControllerType.P,
    ControllerMVBoundType.SMOOTH_BOUND,
    # antiwindup,
    ControllerAntiwindupType.NONE,
)
variable_pairs[m.fs.makeup_mix.makeup.flow_mol] = (
    "h2_production_rate_controller",
    m.fs.h2_mass_production,
    ControllerType.P,
    ControllerMVBoundType.SMOOTH_BOUND,
    ControllerAntiwindupType.NONE,
    # antiwindup,
)
m.fs.add_controllers(variable_pairs)

Now that the controllers have been added to the flowsheet, they need to be tuned and bounds for the MVs need to be set. Additionally, the smooth_eps term used in the SMOOTH_BOUND method of handling variable bounds needs to be tuned to the size of the MV. A heuristic is to use \(10^{-3}\) or \(10^{-4}\) a typical value of the MV.

K = 10e4
tau_I = 15*60
tau_D = 5*60
m.fs.feed_heater_inner_controller.gain_p.fix(K)
m.fs.feed_heater_inner_controller.gain_i.fix(K/tau_I)
m.fs.feed_heater_inner_controller.mv_lb = 0
m.fs.feed_heater_inner_controller.mv_ub = 10e6
m.fs.feed_heater_inner_controller.smooth_eps = 1000
if antiwindup == ControllerAntiwindupType.BACK_CALCULATION:
    m.fs.feed_heater_inner_controller.gain_b.fix(0.5/tau_I)

K =20e4
tau_I = 15*60
tau_D = 5*60
m.fs.sweep_heater_inner_controller.gain_p.fix(K)
m.fs.sweep_heater_inner_controller.gain_i.fix(K/tau_I)
m.fs.sweep_heater_inner_controller.mv_lb = 0
m.fs.sweep_heater_inner_controller.mv_ub = 10e6
m.fs.sweep_heater_inner_controller.smooth_eps = 1000
if antiwindup == ControllerAntiwindupType.BACK_CALCULATION:
    m.fs.sweep_heater_inner_controller.gain_b.fix(0.5/tau_I)

K = 0.75
tau_I = 60*60
m.fs.feed_heater_outer_controller.gain_p.fix(K)

K = 0.75
tau_I = 60*60
m.fs.sweep_heater_outer_controller.gain_p.fix(K)

K = -2
tau_I = 240
m.fs.voltage_controller.gain_p.fix(K)
m.fs.voltage_controller.gain_i.fix(K/tau_I)
m.fs.voltage_controller.mv_lb = 0.7
m.fs.voltage_controller.mv_ub = 1.6
m.fs.voltage_controller.smooth_eps = 0.01
if antiwindup == ControllerAntiwindupType.BACK_CALCULATION:
    m.fs.voltage_controller.gain_b.fix(0.5/tau_I)

K = -50
tau_I = 40 * 60
m.fs.sweep_blower_controller.gain_p.fix(K)
m.fs.sweep_blower_controller.mv_lb = 1500
m.fs.sweep_blower_controller.mv_ub = 10000
m.fs.sweep_blower_controller.smooth_eps = 10

K = 200
tau_I = 20 * 60
m.fs.h2_production_rate_controller.gain_p.fix(K)
m.fs.h2_production_rate_controller.mv_lb = 1
m.fs.h2_production_rate_controller.mv_ub = 1500
m.fs.h2_production_rate_controller.smooth_eps = 1

Most MVs we want to ramp between the old and new setpoints, but there are a few, especially when changing the controller gain, that we need to step.

step_mvs = ComponentSet([])
step_mvs.add(m.fs.voltage_controller.mv_ref)
step_mvs.add(m.fs.voltage_controller.setpoint)
step_mvs.add(m.fs.makeup_mix.makeup_mole_frac_comp_H2)
step_mvs.add(m.fs.makeup_mix.makeup_mole_frac_comp_H2O)
step_mvs.add(m.fs.h2_production_rate_controller.setpoint)
step_mvs.add(m.fs.h2_production_rate_controller.gain_p)

ramp_mvs = m.fs.manipulated_variables - step_mvs

create_ramping_eqns(m.fs, ramp_mvs, 1)

In the present system of scaling, we cannot guarantee that controller MVs and CVs have had scaling factors set when a controller is scaled, so we need to iterate through the controllers and scale them again after the fact.

for ctrl in m.fs.controller_set:
    iscale.calculate_scaling_factors(ctrl)
    iscale.calculate_scaling_factors(ctrl)

Discretize the time domain. We choose time_nfe to be one less than the length of m.fs.time so that Pyomo doesn’t create any additional time points. After the time discretization equations are created, they are then scaled.

time_nfe = len(m.fs.time) - 1
pyo.TransformationFactory("dae.finite_difference").apply_to(
    m.fs, nfe=time_nfe, wrt=m.fs.time, scheme="BACKWARD"
)
iscale.scale_time_discretization_equations(m, m.fs.time, 1/(60*5))

Load and fix the right initial condition. The .json.gz file is generated beforehand by a steady-state optimization. In this case, all these files are pregenerated and committed to the examples repo.

Since we are loading an initial condition from a file, we don’t need to solve a steady state problem at t=0. Therefore, we need to fix variables corresponding to the differential variables of the system and deactivate certain equations that become degenerate.

if operating_scenario == OperatingScenario.maximum_production:
    ms.from_json(m, fname="max_production.json.gz", wts=ms.StoreSpec.value())
elif operating_scenario == OperatingScenario.power_mode:
    ms.from_json(m, fname="power_mode.json.gz", wts=ms.StoreSpec.value())

m.fs.fix_initial_conditions()

Now that we have loaded an initial condition, we can view it in the flowsheet. The write_pfd function iterates through a template .svg file and adds numbers to it by comparing the object name in the .svg to tags in the flowsheet.

m.fs.write_pfd(fname="soc_dynamic_flowsheet.svg")
display(
    "SOC Dynamic Flowsheet",
    SVG(filename="soc_dynamic_flowsheet.svg"),
)
'SOC Dynamic Flowsheet'
../../../_images/e773c9344fbac2bfc55dbef88513a4014b2b9dec41881226ff29c90d835e8ffd.svg

We create a ComponentMap to translate between the column names in soec_flowsheet_operating_conditions.csv to the variables in the actual flowsheet so we can use them as setpoints.

alias_dict = ComponentMap()
alias_dict[m.fs.voltage_controller.mv_ref] = "potential"
alias_dict[m.fs.voltage_controller.setpoint] = "soc_fuel_outlet_mole_frac_comp_H2"
alias_dict[m.fs.soc_module.fuel_outlet_mole_frac_comp_H2] = "soc_fuel_outlet_mole_frac_comp_H2"
alias_dict[m.fs.h2_production_rate_controller.mv_ref] = "makeup_feed_rate"
alias_dict[m.fs.h2_production_rate_controller.setpoint] = "h2_production_rate"
alias_dict[m.fs.h2_production_rate_controller.gain_p] = "h2_production_rate_controller_gain_p"
alias_dict[m.fs.sweep_blower_controller.mv_ref] = "sweep_feed_rate"
alias_dict[m.fs.sweep_blower_controller.setpoint] = "stack_core_temperature"
alias_dict[m.fs.feed_heater_inner_controller.mv_ref] = "feed_heater_duty"
alias_dict[m.fs.feed_heater_outer_controller.mv_ref] = "feed_heater_outlet_temperature"
alias_dict[m.fs.feed_heater_outer_controller.setpoint] = "fuel_outlet_temperature"
alias_dict[m.fs.sweep_heater_inner_controller.mv_ref] = "sweep_heater_duty"
alias_dict[m.fs.sweep_heater_outer_controller.mv_ref] = "sweep_heater_outlet_temperature"
alias_dict[m.fs.sweep_heater_outer_controller.setpoint] = "sweep_outlet_temperature"
alias_dict[m.fs.makeup_mix.makeup_mole_frac_comp_H2] = "makeup_mole_frac_comp_H2"
alias_dict[m.fs.makeup_mix.makeup_mole_frac_comp_H2O] = "makeup_mole_frac_comp_H2O"
alias_dict[m.fs.condenser_flash.vap_outlet.temperature] = "condenser_hot_outlet_temperature"

alias_dict[m.fs.sweep_recycle_split.recycle_ratio] = "sweep_recycle_ratio"

alias_dict[m.fs.feed_recycle_split.recycle_ratio] = "fuel_recycle_ratio"
alias_dict[m.fs.condenser_split.recycle_ratio] = "vgr_recycle_ratio"

df = pd.read_csv("soec_flowsheet_operating_conditions.csv", index_col=0)

These loops iterate through the flowsheet and fix ramp rate variables or set variables to the appropriate values for the given setpoints.

t0 = m.fs.time.first()
for var in ramp_mvs:
    shortname = var.name.split(".")[-1]
    alias = alias_dict[var]
    blk = var.parent_block()
    v_ramp = getattr(blk, shortname + "_ramp_rate")
    var[t0].fix(float(df[alias][setpoints[0]]))
    for i, t in enumerate(time_set):
        v_ramp[t].fix(float(
            (df[alias][setpoints[i]] - df[alias][setpoints[i-1]])
            / (time_set[i] - time_set[i-1])
        ))

for var in step_mvs:
    shortname = var.name.split(".")[-1]
    alias = alias_dict[var]
    for i, t in enumerate(time_set):
        var[t].fix(float(df[alias][setpoints[i]]))

Here we initialize the controllers. Unit model .initialize methods tend to be for steady state optimization, so we manually set variable values and calculate variables from constraints.

# Need to initialize the setpoint for the inner controller or else it starts with the default value 0.5.
m.fs.feed_heater_inner_controller.setpoint[0].value = m.fs.feed_heater_outer_controller.mv_ref[0].value
m.fs.sweep_heater_inner_controller.setpoint[0].value = m.fs.sweep_heater_outer_controller.mv_ref[0].value
for ctrl in m.fs.controller_set:
    if hasattr(ctrl, "mv_eqn"):
        calculate_variable_from_constraint(ctrl.manipulated_var[0], ctrl.mv_eqn[0])

Here we run PETSc to integrate the flowsheet with the TS integrator. Because we are loading from a solved flowsheet, in principle we could set skip_initial=True. However, due to user error there is sometimes a discrepancy between the setpoints loaded and the initial conditions loaded, so we leave it in. There are many options for PETSc-TS that can be read about in the PETSc documentation.

idaeslog.solver_log.tee = True
results = petsc.petsc_dae_by_time_element(
    m,
    time=m.fs.time,
    keepfiles=True,
    symbolic_solver_labels=True,
    ts_options={
        "--ts_type": "beuler",
        "--ts_dt": 0.1,
        "--ts_rtol": 1e-3,
        # "--ts_adapt_clip":"0.001,3600",
        # "--ksp_monitor":"",
        "--ts_adapt_dt_min": 1e-3,
        "--ts_adapt_dt_max": 3600,
        "--snes_type": "newtontr",
        # "--ts_max_reject": 200,
        # "--snes_monitor":"",
        "--ts_monitor": "",
        "--ts_save_trajectory": 1,
        "--ts_trajectory_type": "visualization",
        "--ts_max_snes_failures": 25,
        # "--show_cl":"",
        "-snes_max_it": 50,
        "-snes_rtol": 0,
        "-snes_stol": 0,
        "-snes_atol": 1e-6,
    },
    skip_initial=False,
    initial_solver="ipopt",
    initial_solver_options={
        "constr_viol_tol": 1e-8,
        "nlp_scaling_method": "user-scaling",
        "linear_solver": "ma57",
        "OF_ma57_automatic_scaling": "yes",
        "max_iter": 300,
        "tol": 1e-8,
        "halt_on_ampl_error": "no",
    },
)
for result in results.results:
    pyo.assert_optimal_termination(result)
2024-04-24 16:45:08 [INFO] idaes.solve.petsc-dae: WARNING: model contains export suffix 'scaling_factor' that contains 243
2024-04-24 16:45:08 [INFO] idaes.solve.petsc-dae: component keys that are not exported as part of the NL file.  Skipping.
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Ipopt 3.13.2: constr_viol_tol=1e-08
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: nlp_scaling_method=user-scaling
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: linear_solver=ma57
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: max_iter=300
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: tol=1e-08
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: halt_on_ampl_error=no
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: option_file_name=C:\Users\dallan\AppData\Local\Temp\tmphl5vnriw_ipopt.opt
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: 
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Using option file "C:\Users\dallan\AppData\Local\Temp\tmphl5vnriw_ipopt.opt".
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: 
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: 
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: ******************************************************************************
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: This program contains Ipopt, a library for large-scale nonlinear optimization.
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae:  Ipopt is released as open source code under the Eclipse Public License (EPL).
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae:          For more information visit http://projects.coin-or.org/Ipopt
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: 
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: This version of Ipopt was compiled from source code available at
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae:     https://github.com/IDAES/Ipopt as part of the Institute for the Design of
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae:     Advanced Energy Systems Process Systems Engineering Framework (IDAES PSE
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae:     Framework) Copyright (c) 2018-2019. See https://github.com/IDAES/idaes-pse.
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: 
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: This version of Ipopt was compiled using HSL, a collection of Fortran codes
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae:     for large-scale scientific computation.  All technical papers, sales and
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae:     publicity material resulting from use of the HSL codes within IPOPT must
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae:     contain the following acknowledgement:
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae:         HSL, a collection of Fortran codes for large-scale scientific
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae:         computation. See http://www.hsl.rl.ac.uk.
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: ******************************************************************************
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: 
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: This is Ipopt version 3.13.2, running with linear solver ma57.
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: 
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Number of nonzeros in equality constraint Jacobian...:    15011
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Number of nonzeros in inequality constraint Jacobian.:        0
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Number of nonzeros in Lagrangian Hessian.............:     9356
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: 
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Total number of variables............................:     3864
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae:                      variables with only lower bounds:      667
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae:                 variables with lower and upper bounds:     1495
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae:                      variables with only upper bounds:       31
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Total number of equality constraints.................:     3864
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Total number of inequality constraints...............:        0
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae:         inequality constraints with only lower bounds:        0
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae:    inequality constraints with lower and upper bounds:        0
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae:         inequality constraints with only upper bounds:        0
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: 
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae:    0  0.0000000e+00 6.79e+01 1.00e+00  -1.0 0.00e+00    -  0.00e+00 0.00e+00   0
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Reallocating memory for MA57: lfact (331665)
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae:    1  0.0000000e+00 9.77e-01 1.41e+02  -1.0 5.95e+00    -  8.13e-01 9.85e-01h  1
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae:    2  0.0000000e+00 9.25e-03 1.71e+02  -1.0 8.74e-02    -  9.90e-01 9.90e-01h  1
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae:    3  0.0000000e+00 3.08e-05 2.80e+04  -1.0 6.27e-03    -  9.91e-01 9.97e-01h  1
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae:    4  0.0000000e+00 3.05e-11 4.27e+03  -1.0 7.30e-04    -  1.00e+00 1.00e+00h  1
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: 
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Number of Iterations....: 4
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: 
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae:                                    (scaled)                 (unscaled)
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Objective...............:   0.0000000000000000e+00    0.0000000000000000e+00
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Dual infeasibility......:   0.0000000000000000e+00    0.0000000000000000e+00
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Constraint violation....:   3.0518305330767825e-11    3.0518305330767825e-11
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Complementarity.........:   0.0000000000000000e+00    0.0000000000000000e+00
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Overall NLP error.......:   3.0518305330767825e-11    3.0518305330767825e-11
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: 
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: 
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Number of objective function evaluations             = 5
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Number of objective gradient evaluations             = 5
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Number of equality constraint evaluations            = 5
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Number of inequality constraint evaluations          = 0
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Number of equality constraint Jacobian evaluations   = 5
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Number of inequality constraint Jacobian evaluations = 0
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Number of Lagrangian Hessian evaluations             = 4
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Total CPU secs in IPOPT (w/o function evaluations)   =      0.260
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: Total CPU secs in NLP function evaluations           =      0.041
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: 
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: EXIT: Optimal Solution Found.
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_l
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_h
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_l_nan
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_h_nan
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_l_ext
2024-04-24 16:45:14 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_h_ext
2024-04-24 16:45:22 [INFO] idaes.solve.petsc-dae: WARNING: model contains export suffix 'scaling_factor' that contains 93
2024-04-24 16:45:22 [INFO] idaes.solve.petsc-dae: component keys that are not exported as part of the NL file.  Skipping.
2024-04-24 16:45:22 [INFO] idaes.solve.petsc-dae: Solver log file: 'C:\Users\dallan\AppData\Local\Temp\tmp69gau4jt_petsc_ts.log'
2024-04-24 16:45:22 [INFO] idaes.solve.petsc-dae: Solver solution file: 'C:\Users\dallan\AppData\Local\Temp\tmpva9yq47l.pyomo.sol'
2024-04-24 16:45:22 [INFO] idaes.solve.petsc-dae: Solver problem files: ('C:\\Users\\dallan\\AppData\\Local\\Temp\\tmpva9yq47l.pyomo.nl',)
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: Called fg_read, err: 0 (0 is good)
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: ---------------------------------------------------
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: DAE: 1
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: Reading nl file: C:\Users\dallan\AppData\Local\Temp\tmpva9yq47l.pyomo.nl
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: Number of constraints: 3920
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: Number of nonlinear constraints: 1795
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: Number of linear constraints: 2125
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: Number of inequalities: 0
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: Number of variables: 4007
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: Number of integers: 0
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: Number of binary: 0
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: Number of objectives: 0 (Ignoring)
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: Number of non-zeros in Jacobian: 15554 
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: Explicit time variable: 0
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: Number of derivatives: 87
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: Number of differential vars: 87
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: Number of algebraic vars: 3833
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: Number of state vars: 3920
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: Number of degrees of freedom: 0
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: ---------------------------------------------------
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: 0 TS dt 0.1 time 0.
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: 1 TS dt 0.1 time 0.1
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: 2 TS dt 0.100412 time 0.2
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: 3 TS dt 1.00412 time 0.300412
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: 4 TS dt 10.0412 time 1.30453
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: 5 TS dt 21.1594 time 11.3457
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: 6 TS dt 34.1485 time 32.5051
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: 7 TS dt 56.7094 time 66.6536
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: 8 TS dt 103.25 time 123.363
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: 9 TS dt 205.123 time 226.612
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: 10 TS dt 309.964 time 431.736
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: 11 TS dt 432.696 time 741.7
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: 12 TS dt 621.577 time 1174.4
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: 13 TS dt 902.014 time 1795.97
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: 14 TS dt 902.014 time 2697.99
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: 15 TS dt 2466.59 time 3600.
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: TSConvergedReason = TS_CONVERGED_TIME
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: TS_CONVERGED_TIME
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_l
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_h
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_l_nan
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_h_nan
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_l_ext
2024-04-24 16:45:23 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_h_ext
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: WARNING: model contains export suffix 'scaling_factor' that contains 170
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: component keys that are not exported as part of the NL file.  Skipping.
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: Solver log file: 'C:\Users\dallan\AppData\Local\Temp\tmpn0tqghes_petsc_ts.log'
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: Solver solution file: 'C:\Users\dallan\AppData\Local\Temp\tmpk0c1pdqp.pyomo.sol'
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: Solver problem files: ('C:\\Users\\dallan\\AppData\\Local\\Temp\\tmpk0c1pdqp.pyomo.nl',)
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: Called fg_read, err: 0 (0 is good)
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: ---------------------------------------------------
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: DAE: 1
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: Reading nl file: C:\Users\dallan\AppData\Local\Temp\tmpk0c1pdqp.pyomo.nl
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: Number of constraints: 3920
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: Number of nonlinear constraints: 1795
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: Number of linear constraints: 2125
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: Number of inequalities: 0
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: Number of variables: 4007
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: Number of integers: 0
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: Number of binary: 0
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: Number of objectives: 0 (Ignoring)
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: Number of non-zeros in Jacobian: 15554 
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: Explicit time variable: 0
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: Number of derivatives: 87
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: Number of differential vars: 87
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: Number of algebraic vars: 3833
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: Number of state vars: 3920
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: Number of degrees of freedom: 0
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: ---------------------------------------------------
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: 0 TS dt 0.1 time 3600.
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: 1 TS dt 0.1 time 3600.1
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: 2 TS dt 0.00199239 time 3600.1
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: 3 TS dt 0.0199239 time 3600.1
2024-04-24 16:45:28 [INFO] idaes.solve.petsc-dae: 4 TS dt 0.199239 time 3600.12
2024-04-24 16:45:29 [INFO] idaes.solve.petsc-dae: 5 TS dt 0.697133 time 3600.32
2024-04-24 16:45:29 [INFO] idaes.solve.petsc-dae: 6 TS dt 0.866231 time 3601.02
2024-04-24 16:45:29 [INFO] idaes.solve.petsc-dae: 7 TS dt 1.13013 time 3601.89
2024-04-24 16:45:29 [INFO] idaes.solve.petsc-dae: 8 TS dt 1.179 time 3603.02
2024-04-24 16:45:29 [INFO] idaes.solve.petsc-dae: 9 TS dt 1.3192 time 3604.19
2024-04-24 16:45:29 [INFO] idaes.solve.petsc-dae: 10 TS dt 1.33644 time 3605.51
2024-04-24 16:45:29 [INFO] idaes.solve.petsc-dae: 11 TS dt 1.45894 time 3606.85
2024-04-24 16:45:29 [INFO] idaes.solve.petsc-dae: 12 TS dt 1.46098 time 3608.31
2024-04-24 16:45:29 [INFO] idaes.solve.petsc-dae: 13 TS dt 1.37246 time 3609.77
2024-04-24 16:45:30 [INFO] idaes.solve.petsc-dae: 14 TS dt 1.48172 time 3611.14
2024-04-24 16:45:30 [INFO] idaes.solve.petsc-dae: 15 TS dt 1.2735 time 3612.35
2024-04-24 16:45:30 [INFO] idaes.solve.petsc-dae: 16 TS dt 1.52602 time 3613.63
2024-04-24 16:45:30 [INFO] idaes.solve.petsc-dae: 17 TS dt 1.64143 time 3615.15
2024-04-24 16:45:30 [INFO] idaes.solve.petsc-dae: 18 TS dt 1.5531 time 3616.8
2024-04-24 16:45:30 [INFO] idaes.solve.petsc-dae: 19 TS dt 1.61899 time 3618.35
2024-04-24 16:45:30 [INFO] idaes.solve.petsc-dae: 20 TS dt 1.8938 time 3619.97
2024-04-24 16:45:30 [INFO] idaes.solve.petsc-dae: 21 TS dt 2.14371 time 3621.86
2024-04-24 16:45:30 [INFO] idaes.solve.petsc-dae: 22 TS dt 1.95341 time 3624.01
2024-04-24 16:45:31 [INFO] idaes.solve.petsc-dae: 23 TS dt 0.593203 time 3624.34
2024-04-24 16:45:31 [INFO] idaes.solve.petsc-dae: 24 TS dt 2.07741 time 3624.94
2024-04-24 16:45:31 [INFO] idaes.solve.petsc-dae: 25 TS dt 1.8343 time 3626.78
2024-04-24 16:45:31 [INFO] idaes.solve.petsc-dae: 26 TS dt 2.34236 time 3628.62
2024-04-24 16:45:31 [INFO] idaes.solve.petsc-dae: 27 TS dt 2.70968 time 3630.96
2024-04-24 16:45:31 [INFO] idaes.solve.petsc-dae: 28 TS dt 3.17793 time 3633.67
2024-04-24 16:45:31 [INFO] idaes.solve.petsc-dae: 29 TS dt 2.08994 time 3635.54
2024-04-24 16:45:31 [INFO] idaes.solve.petsc-dae: 30 TS dt 1.32652 time 3637.01
2024-04-24 16:45:32 [INFO] idaes.solve.petsc-dae: 31 TS dt 3.93769 time 3638.34
2024-04-24 16:45:32 [INFO] idaes.solve.petsc-dae: 32 TS dt 3.47399 time 3641.79
2024-04-24 16:45:32 [INFO] idaes.solve.petsc-dae: 33 TS dt 4.44515 time 3645.27
2024-04-24 16:45:32 [INFO] idaes.solve.petsc-dae: 34 TS dt 4.54859 time 3649.71
2024-04-24 16:45:32 [INFO] idaes.solve.petsc-dae: 35 TS dt 5.11148 time 3654.26
2024-04-24 16:45:32 [INFO] idaes.solve.petsc-dae: 36 TS dt 5.37965 time 3659.37
2024-04-24 16:45:32 [INFO] idaes.solve.petsc-dae: 37 TS dt 5.84736 time 3664.75
2024-04-24 16:45:32 [INFO] idaes.solve.petsc-dae: 38 TS dt 6.21996 time 3670.6
2024-04-24 16:45:32 [INFO] idaes.solve.petsc-dae: 39 TS dt 6.69274 time 3676.82
2024-04-24 16:45:32 [INFO] idaes.solve.petsc-dae: 40 TS dt 7.14526 time 3683.51
2024-04-24 16:45:33 [INFO] idaes.solve.petsc-dae: 41 TS dt 7.65699 time 3690.66
2024-04-24 16:45:33 [INFO] idaes.solve.petsc-dae: 42 TS dt 8.18317 time 3698.31
2024-04-24 16:45:33 [INFO] idaes.solve.petsc-dae: 43 TS dt 8.74315 time 3706.5
2024-04-24 16:45:33 [INFO] idaes.solve.petsc-dae: 44 TS dt 9.27856 time 3715.24
2024-04-24 16:45:33 [INFO] idaes.solve.petsc-dae: 45 TS dt 9.68853 time 3724.52
2024-04-24 16:45:33 [INFO] idaes.solve.petsc-dae: 46 TS dt 9.77885 time 3734.21
2024-04-24 16:45:33 [INFO] idaes.solve.petsc-dae: 47 TS dt 9.92111 time 3743.99
2024-04-24 16:45:33 [INFO] idaes.solve.petsc-dae: 48 TS dt 8.33461 time 3752.18
2024-04-24 16:45:33 [INFO] idaes.solve.petsc-dae: 49 TS dt 8.96337 time 3760.51
2024-04-24 16:45:33 [INFO] idaes.solve.petsc-dae: 50 TS dt 9.29772 time 3769.48
2024-04-24 16:45:33 [INFO] idaes.solve.petsc-dae: 51 TS dt 9.60548 time 3778.77
2024-04-24 16:45:34 [INFO] idaes.solve.petsc-dae: 52 TS dt 11.0593 time 3788.38
2024-04-24 16:45:34 [INFO] idaes.solve.petsc-dae: 53 TS dt 9.88706 time 3797.26
2024-04-24 16:45:34 [INFO] idaes.solve.petsc-dae: 54 TS dt 9.88436 time 3807.15
2024-04-24 16:45:34 [INFO] idaes.solve.petsc-dae: 55 TS dt 7.55235 time 3814.54
2024-04-24 16:45:34 [INFO] idaes.solve.petsc-dae: 56 TS dt 9.65705 time 3822.09
2024-04-24 16:45:34 [INFO] idaes.solve.petsc-dae: 57 TS dt 11.0499 time 3831.75
2024-04-24 16:45:34 [INFO] idaes.solve.petsc-dae: 58 TS dt 12.2975 time 3842.8
2024-04-24 16:45:34 [INFO] idaes.solve.petsc-dae: 59 TS dt 12.6609 time 3855.1
2024-04-24 16:45:35 [INFO] idaes.solve.petsc-dae: 60 TS dt 13.9163 time 3859.75
2024-04-24 16:45:35 [INFO] idaes.solve.petsc-dae: 61 TS dt 10.4683 time 3870.54
2024-04-24 16:45:35 [INFO] idaes.solve.petsc-dae: 62 TS dt 9.49383 time 3881.01
2024-04-24 16:45:35 [INFO] idaes.solve.petsc-dae: 63 TS dt 9.49383 time 3890.51
2024-04-24 16:45:35 [INFO] idaes.solve.petsc-dae: 64 TS dt 14.0081 time 3900.
2024-04-24 16:45:35 [INFO] idaes.solve.petsc-dae: TSConvergedReason = TS_CONVERGED_TIME
2024-04-24 16:45:35 [INFO] idaes.solve.petsc-dae: TS_CONVERGED_TIME
2024-04-24 16:45:35 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_l
2024-04-24 16:45:35 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_h
2024-04-24 16:45:35 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_l_nan
2024-04-24 16:45:35 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_h_nan
2024-04-24 16:45:35 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_l_ext
2024-04-24 16:45:35 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_h_ext
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: WARNING: model contains export suffix 'scaling_factor' that contains 170
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: component keys that are not exported as part of the NL file.  Skipping.
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: Solver log file: 'C:\Users\dallan\AppData\Local\Temp\tmp3wnf4q2o_petsc_ts.log'
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: Solver solution file: 'C:\Users\dallan\AppData\Local\Temp\tmpcy91h9f0.pyomo.sol'
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: Solver problem files: ('C:\\Users\\dallan\\AppData\\Local\\Temp\\tmpcy91h9f0.pyomo.nl',)
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: Called fg_read, err: 0 (0 is good)
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: ---------------------------------------------------
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: DAE: 1
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: Reading nl file: C:\Users\dallan\AppData\Local\Temp\tmpcy91h9f0.pyomo.nl
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: Number of constraints: 3920
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: Number of nonlinear constraints: 1795
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: Number of linear constraints: 2125
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: Number of inequalities: 0
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: Number of variables: 4007
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: Number of integers: 0
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: Number of binary: 0
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: Number of objectives: 0 (Ignoring)
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: Number of non-zeros in Jacobian: 15554 
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: Explicit time variable: 0
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: Number of derivatives: 87
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: Number of differential vars: 87
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: Number of algebraic vars: 3833
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: Number of state vars: 3920
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: Number of degrees of freedom: 0
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: ---------------------------------------------------
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: 0 TS dt 0.1 time 3900.
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: 1 TS dt 0.1 time 3900.1
2024-04-24 16:45:40 [INFO] idaes.solve.petsc-dae: 2 TS dt 1. time 3900.2
2024-04-24 16:45:41 [INFO] idaes.solve.petsc-dae: 3 TS dt 2.86361 time 3901.2
2024-04-24 16:45:41 [INFO] idaes.solve.petsc-dae: 4 TS dt 3.11474 time 3904.06
2024-04-24 16:45:41 [INFO] idaes.solve.petsc-dae: 5 TS dt 3.95219 time 3907.18
2024-04-24 16:45:41 [INFO] idaes.solve.petsc-dae: 6 TS dt 4.26539 time 3911.13
2024-04-24 16:45:41 [INFO] idaes.solve.petsc-dae: 7 TS dt 4.68321 time 3915.4
2024-04-24 16:45:41 [INFO] idaes.solve.petsc-dae: 8 TS dt 4.75843 time 3920.08
2024-04-24 16:45:41 [INFO] idaes.solve.petsc-dae: 9 TS dt 4.77214 time 3924.84
2024-04-24 16:45:41 [INFO] idaes.solve.petsc-dae: 10 TS dt 4.57975 time 3929.61
2024-04-24 16:45:41 [INFO] idaes.solve.petsc-dae: 11 TS dt 5.10332 time 3934.19
2024-04-24 16:45:41 [INFO] idaes.solve.petsc-dae: 12 TS dt 5.83254 time 3939.29
2024-04-24 16:45:41 [INFO] idaes.solve.petsc-dae: 13 TS dt 6.72867 time 3945.13
2024-04-24 16:45:41 [INFO] idaes.solve.petsc-dae: 14 TS dt 7.50262 time 3951.85
2024-04-24 16:45:41 [INFO] idaes.solve.petsc-dae: 15 TS dt 8.77609 time 3959.36
2024-04-24 16:45:42 [INFO] idaes.solve.petsc-dae: 16 TS dt 9.95946 time 3968.13
2024-04-24 16:45:42 [INFO] idaes.solve.petsc-dae: 17 TS dt 11.4862 time 3978.09
2024-04-24 16:45:42 [INFO] idaes.solve.petsc-dae: 18 TS dt 13.2173 time 3989.58
2024-04-24 16:45:42 [INFO] idaes.solve.petsc-dae: 19 TS dt 15.4588 time 4002.8
2024-04-24 16:45:42 [INFO] idaes.solve.petsc-dae: 20 TS dt 18.2767 time 4018.25
2024-04-24 16:45:42 [INFO] idaes.solve.petsc-dae: 21 TS dt 21.855 time 4036.53
2024-04-24 16:45:42 [INFO] idaes.solve.petsc-dae: 22 TS dt 25.9265 time 4058.39
2024-04-24 16:45:42 [INFO] idaes.solve.petsc-dae: 23 TS dt 29.7008 time 4084.31
2024-04-24 16:45:42 [INFO] idaes.solve.petsc-dae: 24 TS dt 32.3941 time 4114.01
2024-04-24 16:45:42 [INFO] idaes.solve.petsc-dae: 25 TS dt 34.1498 time 4146.41
2024-04-24 16:45:42 [INFO] idaes.solve.petsc-dae: 26 TS dt 34.3963 time 4180.56
2024-04-24 16:45:42 [INFO] idaes.solve.petsc-dae: 27 TS dt 37.1487 time 4214.95
2024-04-24 16:45:42 [INFO] idaes.solve.petsc-dae: 28 TS dt 37.9342 time 4252.1
2024-04-24 16:45:42 [INFO] idaes.solve.petsc-dae: 29 TS dt 40.3768 time 4290.04
2024-04-24 16:45:42 [INFO] idaes.solve.petsc-dae: 30 TS dt 42.4218 time 4330.41
2024-04-24 16:45:42 [INFO] idaes.solve.petsc-dae: 31 TS dt 45.0908 time 4372.84
2024-04-24 16:45:43 [INFO] idaes.solve.petsc-dae: 32 TS dt 47.3702 time 4417.93
2024-04-24 16:45:43 [INFO] idaes.solve.petsc-dae: 33 TS dt 49.135 time 4465.3
2024-04-24 16:45:43 [INFO] idaes.solve.petsc-dae: 34 TS dt 49.6503 time 4514.43
2024-04-24 16:45:43 [INFO] idaes.solve.petsc-dae: 35 TS dt 51.6702 time 4564.08
2024-04-24 16:45:43 [INFO] idaes.solve.petsc-dae: 36 TS dt 53.1554 time 4615.75
2024-04-24 16:45:43 [INFO] idaes.solve.petsc-dae: 37 TS dt 54.6803 time 4668.91
2024-04-24 16:45:43 [INFO] idaes.solve.petsc-dae: 38 TS dt 61.8766 time 4723.59
2024-04-24 16:45:43 [INFO] idaes.solve.petsc-dae: 39 TS dt 62.3182 time 4785.46
2024-04-24 16:45:43 [INFO] idaes.solve.petsc-dae: 40 TS dt 78.6399 time 4847.78
2024-04-24 16:45:43 [INFO] idaes.solve.petsc-dae: 41 TS dt 82.7293 time 4926.42
2024-04-24 16:45:43 [INFO] idaes.solve.petsc-dae: 42 TS dt 90.4869 time 5009.15
2024-04-24 16:45:43 [INFO] idaes.solve.petsc-dae: 43 TS dt 89.7949 time 5099.64
2024-04-24 16:45:43 [INFO] idaes.solve.petsc-dae: 44 TS dt 85.7202 time 5189.43
2024-04-24 16:45:43 [INFO] idaes.solve.petsc-dae: 45 TS dt 88.4188 time 5275.15
2024-04-24 16:45:43 [INFO] idaes.solve.petsc-dae: 46 TS dt 91.9337 time 5363.57
2024-04-24 16:45:43 [INFO] idaes.solve.petsc-dae: 47 TS dt 90.9639 time 5455.51
2024-04-24 16:45:44 [INFO] idaes.solve.petsc-dae: 48 TS dt 99.5246 time 5546.47
2024-04-24 16:45:44 [INFO] idaes.solve.petsc-dae: 49 TS dt 108.67 time 5645.99
2024-04-24 16:45:44 [INFO] idaes.solve.petsc-dae: 50 TS dt 120.748 time 5754.66
2024-04-24 16:45:44 [INFO] idaes.solve.petsc-dae: 51 TS dt 132.47 time 5875.41
2024-04-24 16:45:44 [INFO] idaes.solve.petsc-dae: 52 TS dt 145.985 time 6007.88
2024-04-24 16:45:44 [INFO] idaes.solve.petsc-dae: 53 TS dt 160.665 time 6153.87
2024-04-24 16:45:44 [INFO] idaes.solve.petsc-dae: 54 TS dt 177.438 time 6314.53
2024-04-24 16:45:44 [INFO] idaes.solve.petsc-dae: 55 TS dt 192.168 time 6491.97
2024-04-24 16:45:44 [INFO] idaes.solve.petsc-dae: 56 TS dt 221.56 time 6684.14
2024-04-24 16:45:44 [INFO] idaes.solve.petsc-dae: 57 TS dt 250.729 time 6905.7
2024-04-24 16:45:44 [INFO] idaes.solve.petsc-dae: 58 TS dt 292.659 time 7156.43
2024-04-24 16:45:44 [INFO] idaes.solve.petsc-dae: 59 TS dt 342.344 time 7449.09
2024-04-24 16:45:44 [INFO] idaes.solve.petsc-dae: 60 TS dt 396.307 time 7791.43
2024-04-24 16:45:44 [INFO] idaes.solve.petsc-dae: 61 TS dt 387.849 time 8187.74
2024-04-24 16:45:44 [INFO] idaes.solve.petsc-dae: 62 TS dt 347.808 time 8474.05
2024-04-24 16:45:44 [INFO] idaes.solve.petsc-dae: 63 TS dt 289.931 time 8626.27
2024-04-24 16:45:45 [INFO] idaes.solve.petsc-dae: 64 TS dt 219.289 time 8708.2
2024-04-24 16:45:45 [INFO] idaes.solve.petsc-dae: 65 TS dt 202.344 time 8927.49
2024-04-24 16:45:45 [INFO] idaes.solve.petsc-dae: 66 TS dt 211.265 time 9055.82
2024-04-24 16:45:45 [INFO] idaes.solve.petsc-dae: 67 TS dt 43.6911 time 9087.46
2024-04-24 16:45:45 [INFO] idaes.solve.petsc-dae: 68 TS dt 97.1116 time 9131.15
2024-04-24 16:45:45 [INFO] idaes.solve.petsc-dae: 69 TS dt 116.121 time 9228.26
2024-04-24 16:45:45 [INFO] idaes.solve.petsc-dae: 70 TS dt 163.226 time 9344.39
2024-04-24 16:45:45 [INFO] idaes.solve.petsc-dae: 71 TS dt 202.871 time 9507.61
2024-04-24 16:45:45 [INFO] idaes.solve.petsc-dae: 72 TS dt 262.974 time 9710.48
2024-04-24 16:45:45 [INFO] idaes.solve.petsc-dae: 73 TS dt 295.993 time 9973.46
2024-04-24 16:45:45 [INFO] idaes.solve.petsc-dae: 74 TS dt 275.494 time 10269.4
2024-04-24 16:45:45 [INFO] idaes.solve.petsc-dae: 75 TS dt 277.528 time 10544.9
2024-04-24 16:45:45 [INFO] idaes.solve.petsc-dae: 76 TS dt 277.528 time 10822.5
2024-04-24 16:45:45 [INFO] idaes.solve.petsc-dae: 77 TS dt 405.82 time 11100.
2024-04-24 16:45:45 [INFO] idaes.solve.petsc-dae: TSConvergedReason = TS_CONVERGED_TIME
2024-04-24 16:45:45 [INFO] idaes.solve.petsc-dae: TS_CONVERGED_TIME
2024-04-24 16:45:45 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_l
2024-04-24 16:45:45 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_h
2024-04-24 16:45:45 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_l_nan
2024-04-24 16:45:45 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_h_nan
2024-04-24 16:45:45 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_l_ext
2024-04-24 16:45:45 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_h_ext
2024-04-24 16:45:50 [INFO] idaes.solve.petsc-dae: WARNING: model contains export suffix 'scaling_factor' that contains 170
2024-04-24 16:45:50 [INFO] idaes.solve.petsc-dae: component keys that are not exported as part of the NL file.  Skipping.
2024-04-24 16:45:50 [INFO] idaes.solve.petsc-dae: Solver log file: 'C:\Users\dallan\AppData\Local\Temp\tmp89d3otha_petsc_ts.log'
2024-04-24 16:45:50 [INFO] idaes.solve.petsc-dae: Solver solution file: 'C:\Users\dallan\AppData\Local\Temp\tmpumhqgnkw.pyomo.sol'
2024-04-24 16:45:50 [INFO] idaes.solve.petsc-dae: Solver problem files: ('C:\\Users\\dallan\\AppData\\Local\\Temp\\tmpumhqgnkw.pyomo.nl',)
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: Called fg_read, err: 0 (0 is good)
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: ---------------------------------------------------
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: DAE: 1
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: Reading nl file: C:\Users\dallan\AppData\Local\Temp\tmpumhqgnkw.pyomo.nl
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: Number of constraints: 3920
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: Number of nonlinear constraints: 1795
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: Number of linear constraints: 2125
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: Number of inequalities: 0
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: Number of variables: 4007
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: Number of integers: 0
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: Number of binary: 0
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: Number of objectives: 0 (Ignoring)
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: Number of non-zeros in Jacobian: 15554 
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: Explicit time variable: 0
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: Number of derivatives: 87
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: Number of differential vars: 87
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: Number of algebraic vars: 3833
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: Number of state vars: 3920
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: Number of degrees of freedom: 0
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: ---------------------------------------------------
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: 0 TS dt 0.1 time 11100.
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: 1 TS dt 0.1 time 11100.1
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: 2 TS dt 0.00392524 time 11100.1
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: 3 TS dt 0.0392524 time 11100.1
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: 4 TS dt 0.392524 time 11100.1
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: 5 TS dt 0.760703 time 11100.5
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: 6 TS dt 1.01241 time 11101.3
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: 7 TS dt 0.967184 time 11102.2
2024-04-24 16:45:51 [INFO] idaes.solve.petsc-dae: 8 TS dt 0.999746 time 11103.2
2024-04-24 16:45:52 [INFO] idaes.solve.petsc-dae: 9 TS dt 0.924929 time 11104.
2024-04-24 16:45:52 [INFO] idaes.solve.petsc-dae: 10 TS dt 0.866639 time 11104.9
2024-04-24 16:45:52 [INFO] idaes.solve.petsc-dae: 11 TS dt 0.915231 time 11105.8
2024-04-24 16:45:52 [INFO] idaes.solve.petsc-dae: 12 TS dt 0.858768 time 11106.7
2024-04-24 16:45:52 [INFO] idaes.solve.petsc-dae: 13 TS dt 1.16546 time 11107.6
2024-04-24 16:45:52 [INFO] idaes.solve.petsc-dae: 14 TS dt 1.0729 time 11108.7
2024-04-24 16:45:52 [INFO] idaes.solve.petsc-dae: 15 TS dt 1.40736 time 11109.8
2024-04-24 16:45:52 [INFO] idaes.solve.petsc-dae: 16 TS dt 1.47697 time 11111.2
2024-04-24 16:45:52 [INFO] idaes.solve.petsc-dae: 17 TS dt 1.55373 time 11112.7
2024-04-24 16:45:53 [INFO] idaes.solve.petsc-dae: 18 TS dt 1.4277 time 11114.
2024-04-24 16:45:53 [INFO] idaes.solve.petsc-dae: 19 TS dt 1.07175 time 11115.
2024-04-24 16:45:53 [INFO] idaes.solve.petsc-dae: 20 TS dt 1.32123 time 11116.1
2024-04-24 16:45:53 [INFO] idaes.solve.petsc-dae: 21 TS dt 1.26966 time 11117.4
2024-04-24 16:45:53 [INFO] idaes.solve.petsc-dae: 22 TS dt 0.929849 time 11118.2
2024-04-24 16:45:53 [INFO] idaes.solve.petsc-dae: 23 TS dt 0.37561 time 11118.5
2024-04-24 16:45:53 [INFO] idaes.solve.petsc-dae: 24 TS dt 1.3944 time 11118.9
2024-04-24 16:45:53 [INFO] idaes.solve.petsc-dae: 25 TS dt 1.43845 time 11120.3
2024-04-24 16:45:53 [INFO] idaes.solve.petsc-dae: 26 TS dt 1.90206 time 11121.7
2024-04-24 16:45:54 [INFO] idaes.solve.petsc-dae: 27 TS dt 1.81077 time 11123.6
2024-04-24 16:45:54 [INFO] idaes.solve.petsc-dae: 28 TS dt 1.79649 time 11125.4
2024-04-24 16:45:54 [INFO] idaes.solve.petsc-dae: 29 TS dt 1.70313 time 11127.2
2024-04-24 16:45:54 [INFO] idaes.solve.petsc-dae: 30 TS dt 1.8855 time 11128.9
2024-04-24 16:45:54 [INFO] idaes.solve.petsc-dae: 31 TS dt 1.85638 time 11130.8
2024-04-24 16:45:54 [INFO] idaes.solve.petsc-dae: 32 TS dt 1.85523 time 11132.7
2024-04-24 16:45:54 [INFO] idaes.solve.petsc-dae: 33 TS dt 1.73671 time 11134.5
2024-04-24 16:45:54 [INFO] idaes.solve.petsc-dae: 34 TS dt 1.64306 time 11136.2
2024-04-24 16:45:54 [INFO] idaes.solve.petsc-dae: 35 TS dt 1.52316 time 11137.9
2024-04-24 16:45:54 [INFO] idaes.solve.petsc-dae: 36 TS dt 1.41285 time 11139.2
2024-04-24 16:45:55 [INFO] idaes.solve.petsc-dae: 37 TS dt 1.57227 time 11139.7
2024-04-24 16:45:55 [INFO] idaes.solve.petsc-dae: 38 TS dt 0.96963 time 11140.2
2024-04-24 16:45:55 [INFO] idaes.solve.petsc-dae: 39 TS dt 0.78644 time 11140.8
2024-04-24 16:45:55 [INFO] idaes.solve.petsc-dae: 40 TS dt 0.705073 time 11141.5
2024-04-24 16:45:55 [INFO] idaes.solve.petsc-dae: 41 TS dt 0.621216 time 11142.
2024-04-24 16:45:55 [INFO] idaes.solve.petsc-dae: 42 TS dt 0.62459 time 11142.6
2024-04-24 16:45:55 [INFO] idaes.solve.petsc-dae: 43 TS dt 0.63664 time 11143.2
2024-04-24 16:45:55 [INFO] idaes.solve.petsc-dae: 44 TS dt 0.690959 time 11143.5
2024-04-24 16:45:56 [INFO] idaes.solve.petsc-dae: 45 TS dt 0.430777 time 11144.
2024-04-24 16:45:56 [INFO] idaes.solve.petsc-dae: 46 TS dt 0.410148 time 11144.4
2024-04-24 16:45:56 [INFO] idaes.solve.petsc-dae: 47 TS dt 0.856631 time 11144.9
2024-04-24 16:45:56 [INFO] idaes.solve.petsc-dae: 48 TS dt 0.949106 time 11145.1
2024-04-24 16:45:56 [INFO] idaes.solve.petsc-dae: 49 TS dt 0.570639 time 11145.5
2024-04-24 16:45:56 [INFO] idaes.solve.petsc-dae: 50 TS dt 0.657937 time 11146.1
2024-04-24 16:45:56 [INFO] idaes.solve.petsc-dae: 51 TS dt 0.756228 time 11146.8
2024-04-24 16:45:56 [INFO] idaes.solve.petsc-dae: 52 TS dt 0.960609 time 11147.5
2024-04-24 16:45:56 [INFO] idaes.solve.petsc-dae: 53 TS dt 1.03942 time 11148.2
2024-04-24 16:45:57 [INFO] idaes.solve.petsc-dae: 54 TS dt 0.73841 time 11148.8
2024-04-24 16:45:57 [INFO] idaes.solve.petsc-dae: 55 TS dt 0.723736 time 11149.6
2024-04-24 16:45:57 [INFO] idaes.solve.petsc-dae: 56 TS dt 1.3136 time 11150.3
2024-04-24 16:45:57 [INFO] idaes.solve.petsc-dae: 57 TS dt 1.44703 time 11151.6
2024-04-24 16:45:57 [INFO] idaes.solve.petsc-dae: 58 TS dt 1.78016 time 11153.1
2024-04-24 16:45:57 [INFO] idaes.solve.petsc-dae: 59 TS dt 1.79591 time 11154.8
2024-04-24 16:45:57 [INFO] idaes.solve.petsc-dae: 60 TS dt 1.70487 time 11156.6
2024-04-24 16:45:57 [INFO] idaes.solve.petsc-dae: 61 TS dt 1.63852 time 11157.6
2024-04-24 16:45:57 [INFO] idaes.solve.petsc-dae: 62 TS dt 0.894779 time 11158.4
2024-04-24 16:45:57 [INFO] idaes.solve.petsc-dae: 63 TS dt 0.904928 time 11159.3
2024-04-24 16:45:57 [INFO] idaes.solve.petsc-dae: 64 TS dt 1.51786 time 11160.2
2024-04-24 16:45:57 [INFO] idaes.solve.petsc-dae: 65 TS dt 1.79934 time 11161.7
2024-04-24 16:45:57 [INFO] idaes.solve.petsc-dae: 66 TS dt 2.19124 time 11163.5
2024-04-24 16:45:58 [INFO] idaes.solve.petsc-dae: 67 TS dt 2.39088 time 11165.7
2024-04-24 16:45:58 [INFO] idaes.solve.petsc-dae: 68 TS dt 2.77663 time 11168.1
2024-04-24 16:45:58 [INFO] idaes.solve.petsc-dae: 69 TS dt 2.98602 time 11170.9
2024-04-24 16:45:58 [INFO] idaes.solve.petsc-dae: 70 TS dt 3.19428 time 11173.9
2024-04-24 16:45:58 [INFO] idaes.solve.petsc-dae: 71 TS dt 3.17037 time 11177.1
2024-04-24 16:45:58 [INFO] idaes.solve.petsc-dae: 72 TS dt 3.2767 time 11180.2
2024-04-24 16:45:58 [INFO] idaes.solve.petsc-dae: 73 TS dt 3.70518 time 11183.5
2024-04-24 16:45:58 [INFO] idaes.solve.petsc-dae: 74 TS dt 3.9439 time 11187.2
2024-04-24 16:45:58 [INFO] idaes.solve.petsc-dae: 75 TS dt 4.1184 time 11191.1
2024-04-24 16:45:58 [INFO] idaes.solve.petsc-dae: 76 TS dt 4.51077 time 11195.3
2024-04-24 16:45:58 [INFO] idaes.solve.petsc-dae: 77 TS dt 4.73 time 11199.8
2024-04-24 16:45:58 [INFO] idaes.solve.petsc-dae: 78 TS dt 4.95553 time 11204.5
2024-04-24 16:45:58 [INFO] idaes.solve.petsc-dae: 79 TS dt 5.05272 time 11209.5
2024-04-24 16:45:58 [INFO] idaes.solve.petsc-dae: 80 TS dt 5.07776 time 11214.5
2024-04-24 16:45:59 [INFO] idaes.solve.petsc-dae: 81 TS dt 5.05502 time 11219.6
2024-04-24 16:45:59 [INFO] idaes.solve.petsc-dae: 82 TS dt 5.05021 time 11224.6
2024-04-24 16:45:59 [INFO] idaes.solve.petsc-dae: 83 TS dt 5.29358 time 11229.7
2024-04-24 16:45:59 [INFO] idaes.solve.petsc-dae: 84 TS dt 5.52422 time 11235.
2024-04-24 16:45:59 [INFO] idaes.solve.petsc-dae: 85 TS dt 5.70998 time 11240.5
2024-04-24 16:45:59 [INFO] idaes.solve.petsc-dae: 86 TS dt 5.77308 time 11246.2
2024-04-24 16:45:59 [INFO] idaes.solve.petsc-dae: 87 TS dt 5.68832 time 11252.
2024-04-24 16:45:59 [INFO] idaes.solve.petsc-dae: 88 TS dt 5.21191 time 11257.7
2024-04-24 16:45:59 [INFO] idaes.solve.petsc-dae: 89 TS dt 5.52452 time 11262.9
2024-04-24 16:45:59 [INFO] idaes.solve.petsc-dae: 90 TS dt 5.08208 time 11267.8
2024-04-24 16:45:59 [INFO] idaes.solve.petsc-dae: 91 TS dt 6.0966 time 11269.7
2024-04-24 16:46:00 [INFO] idaes.solve.petsc-dae: 92 TS dt 4.47115 time 11271.1
2024-04-24 16:46:00 [INFO] idaes.solve.petsc-dae: 93 TS dt 4.46473 time 11271.8
2024-04-24 16:46:00 [INFO] idaes.solve.petsc-dae: 94 TS dt 1.64611 time 11273.5
2024-04-24 16:46:00 [INFO] idaes.solve.petsc-dae: 95 TS dt 3.11947 time 11275.2
2024-04-24 16:46:00 [INFO] idaes.solve.petsc-dae: 96 TS dt 3.69342 time 11278.3
2024-04-24 16:46:00 [INFO] idaes.solve.petsc-dae: 97 TS dt 4.85562 time 11282.
2024-04-24 16:46:00 [INFO] idaes.solve.petsc-dae: 98 TS dt 4.86391 time 11286.8
2024-04-24 16:46:00 [INFO] idaes.solve.petsc-dae: 99 TS dt 4.74083 time 11290.1
2024-04-24 16:46:00 [INFO] idaes.solve.petsc-dae: 100 TS dt 3.88706 time 11291.9
2024-04-24 16:46:01 [INFO] idaes.solve.petsc-dae: 101 TS dt 2.36784 time 11293.1
2024-04-24 16:46:01 [INFO] idaes.solve.petsc-dae: 102 TS dt 3.04988 time 11295.5
2024-04-24 16:46:01 [INFO] idaes.solve.petsc-dae: 103 TS dt 3.79675 time 11297.4
2024-04-24 16:46:01 [INFO] idaes.solve.petsc-dae: 104 TS dt 3.41211 time 11299.4
2024-04-24 16:46:01 [INFO] idaes.solve.petsc-dae: 105 TS dt 5.09485 time 11302.8
2024-04-24 16:46:01 [INFO] idaes.solve.petsc-dae: 106 TS dt 6.30524 time 11307.9
2024-04-24 16:46:01 [INFO] idaes.solve.petsc-dae: 107 TS dt 7.14277 time 11314.2
2024-04-24 16:46:01 [INFO] idaes.solve.petsc-dae: 108 TS dt 6.97261 time 11321.4
2024-04-24 16:46:02 [INFO] idaes.solve.petsc-dae: 109 TS dt 6.92383 time 11328.4
2024-04-24 16:46:02 [INFO] idaes.solve.petsc-dae: 110 TS dt 6.31828 time 11335.3
2024-04-24 16:46:02 [INFO] idaes.solve.petsc-dae: 111 TS dt 5.49724 time 11340.5
2024-04-24 16:46:02 [INFO] idaes.solve.petsc-dae: 112 TS dt 4.90343 time 11345.5
2024-04-24 16:46:02 [INFO] idaes.solve.petsc-dae: 113 TS dt 5.24546 time 11350.4
2024-04-24 16:46:02 [INFO] idaes.solve.petsc-dae: 114 TS dt 5.37157 time 11355.6
2024-04-24 16:46:02 [INFO] idaes.solve.petsc-dae: 115 TS dt 5.08981 time 11361.
2024-04-24 16:46:02 [INFO] idaes.solve.petsc-dae: 116 TS dt 5.15951 time 11366.1
2024-04-24 16:46:02 [INFO] idaes.solve.petsc-dae: 117 TS dt 4.68969 time 11371.2
2024-04-24 16:46:03 [INFO] idaes.solve.petsc-dae: 118 TS dt 4.69922 time 11375.9
2024-04-24 16:46:03 [INFO] idaes.solve.petsc-dae: 119 TS dt 4.35928 time 11380.6
2024-04-24 16:46:03 [INFO] idaes.solve.petsc-dae: 120 TS dt 4.01346 time 11385.
2024-04-24 16:46:03 [INFO] idaes.solve.petsc-dae: 121 TS dt 3.60641 time 11388.5
2024-04-24 16:46:03 [INFO] idaes.solve.petsc-dae: 122 TS dt 3.18203 time 11391.7
2024-04-24 16:46:03 [INFO] idaes.solve.petsc-dae: 123 TS dt 2.78627 time 11394.4
2024-04-24 16:46:03 [INFO] idaes.solve.petsc-dae: 124 TS dt 1.58852 time 11396.8
2024-04-24 16:46:03 [INFO] idaes.solve.petsc-dae: 125 TS dt 1.58852 time 11398.4
2024-04-24 16:46:03 [INFO] idaes.solve.petsc-dae: 126 TS dt 1.90429 time 11400.
2024-04-24 16:46:03 [INFO] idaes.solve.petsc-dae: TSConvergedReason = TS_CONVERGED_TIME
2024-04-24 16:46:03 [INFO] idaes.solve.petsc-dae: TS_CONVERGED_TIME
2024-04-24 16:46:03 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_l
2024-04-24 16:46:03 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_h
2024-04-24 16:46:03 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_l_nan
2024-04-24 16:46:03 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_h_nan
2024-04-24 16:46:03 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_l_ext
2024-04-24 16:46:03 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_h_ext
2024-04-24 16:46:08 [INFO] idaes.solve.petsc-dae: WARNING: model contains export suffix 'scaling_factor' that contains 170
2024-04-24 16:46:08 [INFO] idaes.solve.petsc-dae: component keys that are not exported as part of the NL file.  Skipping.
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: Solver log file: 'C:\Users\dallan\AppData\Local\Temp\tmpendl44cj_petsc_ts.log'
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: Solver solution file: 'C:\Users\dallan\AppData\Local\Temp\tmpson30_9f.pyomo.sol'
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: Solver problem files: ('C:\\Users\\dallan\\AppData\\Local\\Temp\\tmpson30_9f.pyomo.nl',)
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: Called fg_read, err: 0 (0 is good)
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: ---------------------------------------------------
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: DAE: 1
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: Reading nl file: C:\Users\dallan\AppData\Local\Temp\tmpson30_9f.pyomo.nl
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: Number of constraints: 3920
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: Number of nonlinear constraints: 1795
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: Number of linear constraints: 2125
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: Number of inequalities: 0
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: Number of variables: 4007
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: Number of integers: 0
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: Number of binary: 0
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: Number of objectives: 0 (Ignoring)
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: Number of non-zeros in Jacobian: 15554 
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: Explicit time variable: 0
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: Number of derivatives: 87
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: Number of differential vars: 87
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: Number of algebraic vars: 3833
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: Number of state vars: 3920
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: Number of degrees of freedom: 0
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: ---------------------------------------------------
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: 0 TS dt 0.1 time 11400.
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: 1 TS dt 0.1 time 11400.1
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: 2 TS dt 1. time 11400.2
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: 3 TS dt 1.73678 time 11401.2
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: 4 TS dt 2.23341 time 11402.9
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: 5 TS dt 2.51853 time 11405.2
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: 6 TS dt 2.72979 time 11407.7
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: 7 TS dt 2.94331 time 11410.4
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: 8 TS dt 3.1084 time 11413.4
2024-04-24 16:46:09 [INFO] idaes.solve.petsc-dae: 9 TS dt 3.33766 time 11416.5
2024-04-24 16:46:10 [INFO] idaes.solve.petsc-dae: 10 TS dt 3.65145 time 11419.8
2024-04-24 16:46:10 [INFO] idaes.solve.petsc-dae: 11 TS dt 3.92962 time 11423.5
2024-04-24 16:46:10 [INFO] idaes.solve.petsc-dae: 12 TS dt 4.4225 time 11427.4
2024-04-24 16:46:10 [INFO] idaes.solve.petsc-dae: 13 TS dt 4.87494 time 11431.8
2024-04-24 16:46:10 [INFO] idaes.solve.petsc-dae: 14 TS dt 5.42871 time 11436.7
2024-04-24 16:46:10 [INFO] idaes.solve.petsc-dae: 15 TS dt 5.98195 time 11442.1
2024-04-24 16:46:10 [INFO] idaes.solve.petsc-dae: 16 TS dt 6.92855 time 11448.1
2024-04-24 16:46:10 [INFO] idaes.solve.petsc-dae: 17 TS dt 8.07333 time 11455.
2024-04-24 16:46:10 [INFO] idaes.solve.petsc-dae: 18 TS dt 9.63979 time 11463.1
2024-04-24 16:46:10 [INFO] idaes.solve.petsc-dae: 19 TS dt 11.702 time 11472.7
2024-04-24 16:46:10 [INFO] idaes.solve.petsc-dae: 20 TS dt 14.5291 time 11484.4
2024-04-24 16:46:10 [INFO] idaes.solve.petsc-dae: 21 TS dt 18.1896 time 11499.
2024-04-24 16:46:10 [INFO] idaes.solve.petsc-dae: 22 TS dt 22.203 time 11517.2
2024-04-24 16:46:10 [INFO] idaes.solve.petsc-dae: 23 TS dt 25.5942 time 11539.4
2024-04-24 16:46:10 [INFO] idaes.solve.petsc-dae: 24 TS dt 28.4541 time 11565.
2024-04-24 16:46:10 [INFO] idaes.solve.petsc-dae: 25 TS dt 30.7952 time 11593.4
2024-04-24 16:46:11 [INFO] idaes.solve.petsc-dae: 26 TS dt 32.9926 time 11624.2
2024-04-24 16:46:11 [INFO] idaes.solve.petsc-dae: 27 TS dt 34.8988 time 11657.2
2024-04-24 16:46:11 [INFO] idaes.solve.petsc-dae: 28 TS dt 37.5398 time 11692.1
2024-04-24 16:46:11 [INFO] idaes.solve.petsc-dae: 29 TS dt 41.8031 time 11729.6
2024-04-24 16:46:11 [INFO] idaes.solve.petsc-dae: 30 TS dt 47.4503 time 11771.4
2024-04-24 16:46:11 [INFO] idaes.solve.petsc-dae: 31 TS dt 53.673 time 11818.9
2024-04-24 16:46:11 [INFO] idaes.solve.petsc-dae: 32 TS dt 60.8933 time 11872.6
2024-04-24 16:46:11 [INFO] idaes.solve.petsc-dae: 33 TS dt 69.4519 time 11933.5
2024-04-24 16:46:11 [INFO] idaes.solve.petsc-dae: 34 TS dt 77.8654 time 12002.9
2024-04-24 16:46:11 [INFO] idaes.solve.petsc-dae: 35 TS dt 85.3528 time 12080.8
2024-04-24 16:46:11 [INFO] idaes.solve.petsc-dae: 36 TS dt 92.584 time 12166.1
2024-04-24 16:46:11 [INFO] idaes.solve.petsc-dae: 37 TS dt 99.6879 time 12258.7
2024-04-24 16:46:11 [INFO] idaes.solve.petsc-dae: 38 TS dt 107.395 time 12358.4
2024-04-24 16:46:11 [INFO] idaes.solve.petsc-dae: 39 TS dt 115.883 time 12465.8
2024-04-24 16:46:11 [INFO] idaes.solve.petsc-dae: 40 TS dt 125.805 time 12581.7
2024-04-24 16:46:12 [INFO] idaes.solve.petsc-dae: 41 TS dt 136.484 time 12707.5
2024-04-24 16:46:12 [INFO] idaes.solve.petsc-dae: 42 TS dt 146.675 time 12844.
2024-04-24 16:46:12 [INFO] idaes.solve.petsc-dae: 43 TS dt 154.432 time 12990.6
2024-04-24 16:46:12 [INFO] idaes.solve.petsc-dae: 44 TS dt 158.051 time 13145.1
2024-04-24 16:46:12 [INFO] idaes.solve.petsc-dae: 45 TS dt 156.722 time 13303.1
2024-04-24 16:46:12 [INFO] idaes.solve.petsc-dae: 46 TS dt 161.592 time 13459.8
2024-04-24 16:46:12 [INFO] idaes.solve.petsc-dae: 47 TS dt 169.876 time 13621.4
2024-04-24 16:46:12 [INFO] idaes.solve.petsc-dae: 48 TS dt 175.501 time 13791.3
2024-04-24 16:46:12 [INFO] idaes.solve.petsc-dae: 49 TS dt 177.773 time 13966.8
2024-04-24 16:46:12 [INFO] idaes.solve.petsc-dae: 50 TS dt 195.829 time 14144.6
2024-04-24 16:46:12 [INFO] idaes.solve.petsc-dae: 51 TS dt 209.215 time 14340.4
2024-04-24 16:46:12 [INFO] idaes.solve.petsc-dae: 52 TS dt 228.235 time 14549.6
2024-04-24 16:46:12 [INFO] idaes.solve.petsc-dae: 53 TS dt 245.428 time 14777.9
2024-04-24 16:46:12 [INFO] idaes.solve.petsc-dae: 54 TS dt 265.796 time 15023.3
2024-04-24 16:46:12 [INFO] idaes.solve.petsc-dae: 55 TS dt 286.41 time 15289.1
2024-04-24 16:46:12 [INFO] idaes.solve.petsc-dae: 56 TS dt 309.614 time 15575.5
2024-04-24 16:46:12 [INFO] idaes.solve.petsc-dae: 57 TS dt 336.559 time 15885.1
2024-04-24 16:46:12 [INFO] idaes.solve.petsc-dae: 58 TS dt 370.237 time 16221.7
2024-04-24 16:46:12 [INFO] idaes.solve.petsc-dae: 59 TS dt 418.152 time 16591.9
2024-04-24 16:46:12 [INFO] idaes.solve.petsc-dae: 60 TS dt 475.299 time 17010.1
2024-04-24 16:46:13 [INFO] idaes.solve.petsc-dae: 61 TS dt 548.284 time 17485.4
2024-04-24 16:46:13 [INFO] idaes.solve.petsc-dae: 62 TS dt 640.182 time 18033.6
2024-04-24 16:46:13 [INFO] idaes.solve.petsc-dae: 63 TS dt 756.084 time 18673.8
2024-04-24 16:46:13 [INFO] idaes.solve.petsc-dae: 64 TS dt 900.068 time 19429.9
2024-04-24 16:46:13 [INFO] idaes.solve.petsc-dae: 65 TS dt 935.01 time 20330.
2024-04-24 16:46:13 [INFO] idaes.solve.petsc-dae: 66 TS dt 935.01 time 21265.
2024-04-24 16:46:13 [INFO] idaes.solve.petsc-dae: 67 TS dt 1415.01 time 22200.
2024-04-24 16:46:13 [INFO] idaes.solve.petsc-dae: TSConvergedReason = TS_CONVERGED_TIME
2024-04-24 16:46:13 [INFO] idaes.solve.petsc-dae: TS_CONVERGED_TIME
2024-04-24 16:46:13 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_l
2024-04-24 16:46:13 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_h
2024-04-24 16:46:13 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_l_nan
2024-04-24 16:46:13 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_h_nan
2024-04-24 16:46:13 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_l_ext
2024-04-24 16:46:13 [INFO] idaes.solve.petsc-dae: addfunc: duplicate function cubic_root_h_ext

Load certain variables into a dictionary for plotting convenience.

ramp_list = np.array(m.fs.time)[1:]
traj = results.trajectory

time_set = m.fs.time.ordered_data()
tf = time_set[-1]
soec = m.fs.soc_module.solid_oxide_cell

results_dict = {
    "ramp_list": np.array(ramp_list),
    "time": np.array(traj.time),
    "potential": np.array(traj.vecs[str(soec.potential[tf])]),
    "current": np.array(traj.vecs[str(m.fs.soc_module.total_current[tf])]),
    "soec_fuel_inlet_flow": np.array(traj.vecs[str(m.fs.soc_module.fuel_inlet.flow_mol[tf])]),
    "soec_oxygen_inlet_flow": np.array(traj.vecs[str(m.fs.soc_module.oxygen_inlet.flow_mol[tf])]),
    "fuel_heater_duty": np.array(traj.vecs[str(m.fs.feed_heater.electric_heat_duty[tf])]),
    "sweep_heater_duty": np.array(traj.vecs[str(m.fs.sweep_heater.electric_heat_duty[tf])]),
    "fuel_inlet_H2": np.array(traj.vecs[str(soec.fuel_inlet.mole_frac_comp[tf, "H2"])]),
    "fuel_inlet_H2O": np.array(traj.vecs[str(soec.fuel_inlet.mole_frac_comp[tf, "H2O"])]),
    "fuel_outlet_H2O": np.array(traj.vecs[str(soec.fuel_channel.mole_frac_comp[tf, soec.iznodes.last(), "H2O",])]),
    "sweep_inlet_O2": np.array(traj.vecs[str(soec.oxygen_inlet.mole_frac_comp[tf, "O2"])]),
    "sweep_outlet_O2": np.array(traj.vecs[str(soec.oxygen_channel.mole_frac_comp[tf, soec.iznodes.first(), "O2"])]),
    "H2_production": np.array(traj.vecs[str(m.fs.h2_mass_production[tf])]),
    "fuel_outlet_mole_frac_comp_H2": np.array(traj.vecs[str(m.fs.soc_module.fuel_outlet_mole_frac_comp_H2[tf])]),
    "steam_feed_rate": np.array(traj.vecs[str(m.fs.makeup_mix.makeup.flow_mol[tf])]),
    "sweep_feed_rate": np.array(traj.vecs[str(m.fs.sweep_blower.inlet.flow_mol[tf])]),
    "total_electric_power": np.array(traj.vecs[str(m.fs.total_electric_power[tf])]),
    "fuel_inlet_temperature": np.array(traj.vecs[str(soec.fuel_channel.temperature_inlet[tf])]) ,
    "sweep_inlet_temperature": np.array(traj.vecs[str(soec.oxygen_channel.temperature_inlet[tf])]) ,
    "stack_core_temperature": np.array(traj.vecs[str(m.fs.stack_core_temperature[tf])]) ,
    "fuel_outlet_temperature": np.array(traj.vecs[str(soec.fuel_channel.temperature_outlet[tf])]) ,
    "sweep_outlet_temperature": np.array(traj.vecs[str(soec.oxygen_channel.temperature_outlet[tf])]) ,
    "product_mole_frac_H2": np.array(
        traj.vecs[str(m.fs.condenser_split.inlet.mole_frac_comp[tf, "H2"])]
    ),
    "condenser_outlet_temperature": np.array(
        traj.vecs[str(m.fs.condenser_flash.control_volume.properties_out[tf].temperature)]
    ),
    "condenser_heat_duty": np.array(
        traj.vecs[str(m.fs.condenser_flash.heat_duty[tf])]
    ),
    "temperature_z": np.array([traj.vecs[str(soec.temperature_z[tf, iz])] for iz in soec.iznodes]) ,
    "fuel_electrode_temperature_deviation_x": np.array(
        [traj.vecs[str(soec.fuel_electrode.temperature_deviation_x[tf, 1, iz])] for iz in soec.iznodes]
    ),
    "interconnect_temperature_deviation_x":np.array(
        [traj.vecs[str(soec.interconnect.temperature_deviation_x[tf, 1, iz])] for iz in soec.iznodes]
    ),
    "temperature_z_gradient": np.array(
        [traj.vecs[str(soec.dtemperature_z_dz[tf, iz])] for iz in soec.iznodes]
    ),
    "fuel_electrode_gradient": np.array(
        [traj.vecs[str(soec.fuel_electrode.dtemperature_dz[tf, 1, iz])] for iz in soec.iznodes]
    ),
    "fuel_electrode_mixed_partial": np.array(
        [traj.vecs[str(soec.fuel_electrode.d2temperature_dzdt_dummy[tf, 1, iz])] for iz in soec.iznodes]
    ),
    "interconnect_gradient": np.array(
        [traj.vecs[str(soec.interconnect.dtemperature_dz[tf, 1, iz])] for iz in soec.iznodes]
    ),
    "current_density": np.array(
        [traj.vecs[str(soec.current_density[tf, iz])] for iz in soec.iznodes]
    ),
    "feed_heater_temperature": np.array(
        [traj.vecs[str(m.fs.feed_heater.temp_wall_center[tf, z])]
            for z in m.fs.feed_heater.control_volume.length_domain]
    ),
    "sweep_heater_temperature": np.array(
        [traj.vecs[str(m.fs.sweep_heater.temp_wall_center[tf, z])]
            for z in m.fs.sweep_heater.control_volume.length_domain]
    ),
    "feed_medium_exchanger_temperature": np.array(
        [traj.vecs[str(m.fs.feed_medium_exchanger.temp_wall_center[tf, z])]
            for z in m.fs.feed_medium_exchanger.cold_side.length_domain]
    ),
    "feed_hot_exchanger_temperature": np.array(
        [traj.vecs[str(m.fs.feed_hot_exchanger.temp_wall_center[tf, z])]
            for z in m.fs.feed_hot_exchanger.cold_side.length_domain]
    ),
    "sweep_exchanger_temperature": np.array(
        [traj.vecs[str(m.fs.sweep_exchanger.temp_wall_center[tf, z])]
            for z in m.fs.sweep_exchanger.cold_side.length_domain]
    ),
}

for controller in m.fs.controller_set:
    ctrl_name = controller.local_name
    results_dict[ctrl_name + "_mv_ref"] = np.array(traj.vecs[str(controller.mv_ref[tf])])
    results_dict[ctrl_name + "_setpoint"] = np.array(traj.vecs[str(controller.setpoint[tf])])

Here we plot a number of system variables that we use to gauge system performance. The user is free to adapt this code to view other variables of interest.

def _demarcate_ramps(ax, results_dict):
    for tpoint in np.squeeze(results_dict["ramp_list"])[:-1]:
        ax.plot(np.array([tpoint, tpoint]) / 60 ** 2, [-1e6, 1e6], 'k--')
include_PI = True

for key, value in results_dict.items():
    # Turn n by 1 arrays in into vectors
    results_dict[key] = np.squeeze(value)

demarcate_ramps = lambda ax: _demarcate_ramps(ax, results_dict)

time = results_dict["time"] / 60 ** 2

ax_fontsize = 14
title_fontsize = 16
iz_plot = [1, 3, 5, 8, 10]

fig = plt.figure()
ax = fig.subplots()

ax.plot(time, results_dict["potential"])
if include_PI:
    ax.plot(
        time,
        results_dict["voltage_controller_mv_ref"],
        color="darkblue",
        linestyle="dotted",
    )
demarcate_ramps(ax)
ax.set_xlim(time[0], time[-1])
ax.set_ylim((0.65, 1.45))
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("Cell potential (V)", fontsize=ax_fontsize)
ax.set_title("SOEC Voltage", fontsize=title_fontsize)

fig = plt.figure()
ax = fig.subplots()

ax.plot(time, results_dict["current"]*1e-6)
demarcate_ramps(ax)
ax.set_xlim(time[0], time[-1])
ax.set_ylim((-250, 125))
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("Current (MA)", fontsize=ax_fontsize)
ax.set_title("Total module current", fontsize=title_fontsize)

fig = plt.figure()
ax = fig.subplots()

ax.plot(time, results_dict["soec_fuel_inlet_flow"], label="Fuel")
ax.plot(time, results_dict["soec_oxygen_inlet_flow"], label="Sweep")
demarcate_ramps(ax)
ax.set_xlim(time[0], time[-1])
ax.set_ylim((0, 20000))
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("SOEC inlet molar flow (mol/s)", fontsize=ax_fontsize)
ax.set_title("Inlet molar flow rates", fontsize=title_fontsize)
ax.legend()

fig = plt.figure()
ax = fig.subplots()
ax.plot(time, 1e-6 * results_dict["fuel_heater_duty"], label="Fuel", color="tab:blue")
ax.plot(time, 1e-6 * results_dict["sweep_heater_duty"], label="Sweep", color="tab:orange")
if include_PI:
    ax.plot(
        time,
        1e-6 * results_dict["feed_heater_inner_controller_mv_ref"],
        label="Fuel reference",
        color="darkblue",
        linestyle="dotted"
    )
    ax.plot(
        time,
        1e-6 * results_dict["sweep_heater_inner_controller_mv_ref"],
        label="Sweep reference",
        color="saddlebrown",
        linestyle="dotted"
    )
demarcate_ramps(ax)
ax.set_xlim(time[0], time[-1])
ax.set_ylim((0, 11))
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("Heater duty (MW)", fontsize=ax_fontsize)
ax.set_title("Trim heater duties", fontsize=title_fontsize)
ax.legend()

fig = plt.figure()
ax = fig.subplots()
ax.plot(time, results_dict["fuel_inlet_H2O"], label="Inlet $H_2O$")
ax.plot(time, results_dict["fuel_outlet_H2O"], label="Outlet $H_2O$")
ax.plot(time, results_dict["sweep_inlet_O2"], label="Inlet $O_2$")
ax.plot(time, results_dict["sweep_outlet_O2"], label="Outlet $O_2$")
ax.plot(time, results_dict["product_mole_frac_H2"], label="Product $H_2$")
ax.plot(time, 0.35 * np.ones(time.shape), '--')
ax.plot(time, 0.25 * np.ones(time.shape), '--')
demarcate_ramps(ax)
ax.set_xlim(time[0], time[-1])
ax.set_ylim((0, 1))
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("Mole fraction", fontsize=ax_fontsize)
ax.set_title("Reactor feed and effluent concentrations", fontsize=title_fontsize)
ax.legend()

fig = plt.figure()
ax = fig.subplots()
ax.plot(time, results_dict["H2_production"])
demarcate_ramps(ax)
ax.set_xlim(time[0], time[-1])
ax.set_ylim((-1.25, 2.5))
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("Hydrogen Production Rate (kg/s)", fontsize=ax_fontsize)
ax.set_title("Instantaneous $H_2$ production rate", fontsize=title_fontsize)

if include_PI:
    ax.plot(
        time,
        results_dict["h2_production_rate_controller_setpoint"],
        label="Target",
        color="darkblue",
        linestyle="dotted"
    )
ax.legend()

fig = plt.figure()
ax = fig.subplots()
ax.plot(time, results_dict["steam_feed_rate"])
if include_PI:
    ax.plot(time,
            results_dict["h2_production_rate_controller_mv_ref"],
            label="Target",
            color="darkblue",
            linestyle="dotted"
    )
demarcate_ramps(ax)
ax.set_xlim(time[0], time[-1])
ax.set_ylim((0, 7500))
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("Steam feed rate (mol/s)", fontsize=ax_fontsize)
ax.set_title("Steam feed rate", fontsize=title_fontsize)
ax.legend()

fig = plt.figure()
ax = fig.subplots()
ax.plot(time, results_dict["sweep_feed_rate"])
if include_PI:
    ax.plot(time,
            results_dict["sweep_blower_controller_mv_ref"],
            label="Target",
            color="darkblue",
            linestyle="dotted"
    )
demarcate_ramps(ax)
ax.set_xlim(time[0], time[-1])
ax.set_ylim((0, 11000))
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("Sweep feed rate (mol/s)", fontsize=ax_fontsize)
ax.set_title("Sweep feed rate", fontsize=title_fontsize)
ax.legend()

fig = plt.figure()
ax = fig.subplots()
ax.plot(time, 1e-6 * results_dict["total_electric_power"], 'b', label="Total power")
demarcate_ramps(ax)
ax.set_xlim(time[0], time[-1])
ax.set_ylim((-125, 350))
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("Power usage (MW)", color="blue", fontsize=ax_fontsize)
ax.set_title("Power usage", fontsize=title_fontsize)

fig = plt.figure()
ax = fig.subplots()

ax.plot(time, results_dict["fuel_inlet_temperature"], label="Fuel", color="tab:blue")
ax.plot(time, results_dict["sweep_inlet_temperature"], label="Sweep", color="tab:orange")
ax.plot(time, results_dict["stack_core_temperature"], label="Stack core", color="darkgreen")

if include_PI:
    ax.plot(
        time,
        results_dict["feed_heater_inner_controller_setpoint"],
        label="Fuel target",
        color="darkblue",
        linestyle="dotted"
    )
    ax.plot(
        time,
        results_dict["sweep_heater_inner_controller_setpoint"],
        label="Sweep target",
        color="saddlebrown",
        linestyle="dotted"
    )
    ax.plot(
        time,
        results_dict["sweep_blower_controller_setpoint"],
        label="Core target",
        color="olivedrab",
        linestyle="dotted"
    )

ax.set_xlim(time[0], time[-1])
ax.set_ylim((850, 1150))
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("Temperature (K)", fontsize=ax_fontsize)
demarcate_ramps(ax)
ax.set_title("SOEC temperature", fontsize=title_fontsize)
ax.legend()

fig = plt.figure()
ax = fig.subplots()

ax.plot(time, results_dict["fuel_outlet_temperature"], label="Fuel", color="tab:blue")
ax.plot(time, results_dict["sweep_outlet_temperature"], label="Sweep", color="tab:orange")
if include_PI:
    ax.plot(
        time,
        results_dict["feed_heater_outer_controller_setpoint"],
        label="Fuel target",
        color="darkblue",
        linestyle="dotted"
    )
    ax.plot(
        time,
        results_dict["sweep_heater_outer_controller_setpoint"],
        label="Sweep target",
        color="saddlebrown",
        linestyle="dotted"
    )

ax.set_xlim(time[0], time[-1])
ax.set_ylim((890, 1100))
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("Temperature (K)", fontsize=ax_fontsize)
demarcate_ramps(ax)
ax.set_title("SOEC outlet temperature", fontsize=title_fontsize)
ax.legend()

fig = plt.figure()
ax = fig.subplots()

for iz in iz_plot:
    ax.plot(time, results_dict["temperature_z"][iz-1, :], label=f"z node {iz}")

ax.set_xlim(time[0], time[-1])
ax.set_ylim((890, 1100))
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("Temperature (K)", fontsize=ax_fontsize)
demarcate_ramps(ax)
ax.set_title("SOEC temperature profile", fontsize=title_fontsize)
ax.legend()

fig = plt.figure()
ax = fig.subplots()

for iz in iz_plot:
    ax.plot(
        time,
        results_dict["temperature_z"][iz-1, :] + results_dict["fuel_electrode_temperature_deviation_x"][iz-1, :],
        label=f"z node {iz}"
    )

ax.set_xlim(time[0], time[-1])
ax.set_ylim((890, 1100))
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("Temperature (K)", fontsize=ax_fontsize)
demarcate_ramps(ax)
ax.set_title("Temperature electrode", fontsize=title_fontsize)
ax.legend()

fig = plt.figure()
ax = fig.subplots()

for iz in iz_plot:
    ax.plot(
        time,
        results_dict["temperature_z"][iz-1, :] + results_dict["interconnect_temperature_deviation_x"][iz-1, :],
        label=f"z node {iz}"
    )

ax.set_xlim(time[0], time[-1])
ax.set_ylim((890, 1100))
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("Temperature (K)", fontsize=ax_fontsize)
demarcate_ramps(ax)
ax.set_title("Temperature interconnect", fontsize=title_fontsize)
ax.legend()

fig = plt.figure()
ax = fig.subplots()

for iz in iz_plot:
    ax.plot(
        time,
        results_dict["fuel_electrode_gradient"][iz-1, :],
        label=f"node {iz}"
    )

ax.set_xlim(time[0], time[-1])
ax.set_ylim((-1000, 1000))
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("$dT/dz$ ($K/m$)", fontsize=ax_fontsize)
ax.set_title("SOEC PEN temperature gradient", fontsize=title_fontsize)
demarcate_ramps(ax)
ax.legend()

fig = plt.figure()
ax = fig.subplots()

for iz in iz_plot:
    ax.plot(
        time,
        results_dict["fuel_electrode_mixed_partial"][iz-1, :],
        label=f"node {iz}"
    )

ax.set_xlim(time[0], time[-1])
ax.set_ylim((-2, 2))
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("$d^2T/dzdt$ ($K/(m s)$)", fontsize=ax_fontsize)
ax.set_title("SOEC PEN temperature mixed partial", fontsize=title_fontsize)
demarcate_ramps(ax)
ax.legend()

fig = plt.figure()
ax = fig.subplots()

for iz in iz_plot:
    ax.plot(time, results_dict["current_density"][iz-1, :] / 10, label=f"z node {iz}")

ax.set_xlim(time[0], time[-1])
# ax.set_ylim((575,875))
ax.set_ylim((-1000, 650))
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("Current density ($mA/cm^2$)", fontsize=ax_fontsize)
ax.set_title("SOEC current density", fontsize=title_fontsize)
demarcate_ramps(ax)
ax.legend()

fig = plt.figure()
ax = fig.subplots()
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("Temperature (K)", fontsize=ax_fontsize)
for z in range(results_dict["feed_heater_temperature"].shape[0]):
    ax.plot(time, results_dict["feed_heater_temperature"][z, :], label=f"Feed wall node {z+1}")
    ax.plot(time, results_dict["sweep_heater_temperature"][z, :], label=f"Sweep wall node {z+1}")
ax.set_xlim(time[0], time[-1])
ax.set_ylim((870, 1175))
demarcate_ramps(ax)
ax.set_title("Trim heater wall temperature", fontsize=title_fontsize)
ax.legend()

fig = plt.figure()
ax = fig.subplots()
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("Temperature (K)", fontsize=ax_fontsize)
for z in range(results_dict["feed_medium_exchanger_temperature"].shape[0]):
    ax.plot(time,
            results_dict["feed_medium_exchanger_temperature"][z, :],
            label=f"Node {z + 1}")
ax.set_xlim(time[0], time[-1])
ax.set_ylim((370, 520))
demarcate_ramps(ax)
ax.set_title("Medium exchanger wall temperature", fontsize=title_fontsize)
ax.legend()

fig = plt.figure()
ax = fig.subplots()
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("Temperature (K)", fontsize=ax_fontsize)

for z in range(results_dict["feed_hot_exchanger_temperature"].shape[0]):
    ax.plot(time,
            results_dict["feed_hot_exchanger_temperature"][z, :],
            label=f"Node {z + 1}")
ax.set_xlim(time[0], time[-1])
ax.set_ylim((700, 950))
demarcate_ramps(ax)
ax.set_title("Hot exchanger wall temperature", fontsize=title_fontsize)
ax.legend()

fig = plt.figure()
ax = fig.subplots()
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("Temperature (K)", fontsize=ax_fontsize)
for z in range(results_dict["sweep_exchanger_temperature"].shape[0]):
    ax.plot(time,
            results_dict["sweep_exchanger_temperature"][z, :],
            label=f"Node {z}")
ax.set_xlim(time[0], time[-1])
ax.set_ylim((700, 1020))
demarcate_ramps(ax)
ax.set_title("Sweep exchanger wall temperature", fontsize=title_fontsize)
ax.legend()

fig = plt.figure()
ax = fig.subplots()
ax2 = ax.twinx()

ax.plot(time, results_dict["condenser_outlet_temperature"], label="Temperature", color="tab:blue")
ax2.plot(time, results_dict["product_mole_frac_H2"], label="H2 mole fraction", color="tab:orange")

ax.set_xlim(time[0], time[-1])
ax.set_ylim((273.15, 373.15))
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("Temperature (K)", fontsize=ax_fontsize, color="tab:blue")
ax2.set_ylim((0,1))
ax2.set_ylabel("Mole fraction $H_2$", fontsize=ax_fontsize,  color="tab:orange")

demarcate_ramps(ax)
ax.set_title("Condenser Vapor Outlet", fontsize=title_fontsize)

fig = plt.figure()
ax = fig.subplots()

ax.plot(time, 1e-6*results_dict["condenser_heat_duty"])

ax.set_xlim(time[0], time[-1])
ax.set_ylim((-40, -12))
ax.set_xlabel("Time (hr)", fontsize=ax_fontsize)
ax.set_ylabel("Heat Duty (MW)", fontsize=ax_fontsize)

demarcate_ramps(ax)
ax.set_title("Condenser Heat Duty", fontsize=title_fontsize)

plt.show()
C:\Users\dallan\AppData\Local\Temp\ipykernel_41080\391657263.py:377: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`). Consider using `matplotlib.pyplot.close()`.
  fig = plt.figure()
../../../_images/0c3d5ca131ea93dceef4875595889157c70cf706cef03fddf5e71d41a1f2e108.png ../../../_images/9f16d571485de2a52f2a9e3492d0439db8c451579f8c1e2654c072dceab0519e.png ../../../_images/342d5f2a2ee13178184f1bde87e2a459058e5c8f0d8574642295e7235a936b9a.png ../../../_images/3f06408cc23b5ffeaea1d6623b3fac056e94100e350d0babd6bbb761e8c28784.png ../../../_images/fce9b5f61e01e95f0ccb72dd59db948520e4be238e8c9e9096ddfdd92ec1b357.png ../../../_images/a71a008be7e4c6776545796a8f7cb203a00214e222da3624ab591c4081088953.png ../../../_images/fa93340e1f64f31c1966748ed61fe63fe817c63c3b2bc5b2af96977400651965.png ../../../_images/a7e4a6b92f7a13110ad1757094b6e05191193795107726de57ff4958b8a89be3.png ../../../_images/e963779fc5a196e2fe752f534fe5bca12f76e321895f334a82f714546b4ffee8.png ../../../_images/0b910a876a66a64c91c534a6abe1547ac98ec9de6771cfb171416cc16b31f836.png ../../../_images/c821d912e0c4365464154a4d4a27ede3019ae97a8bd28a8602523d9da86977d0.png ../../../_images/b753690b7547472cf3890cd812b7b5ac40dcfbff767d52160829027f96d054a9.png ../../../_images/bd76fb16ce3ec6a2a259f20f58753109ea3f0ca41af5fd00864f1f417d4b905f.png ../../../_images/98d920dc4049feb69f5dac873205c004fdaa68f35b4c7246c3a37a459ea4d21b.png ../../../_images/8979b2d14e133d33690e7583e541b504177d842103a3e49b789ef661e1ca414b.png ../../../_images/9c66392d7cefaa5bbd251e3d7f7ac2566fb3269074a07a803fe90fcff65617b6.png ../../../_images/f001a6a6e9a0b35633d702996e281d3352d3eb860894051e9f0ecd9e03159c16.png ../../../_images/ba06d5a141da25ee220a13afc54fda521dad4819ac066928f5a2c9415b6b2a6a.png ../../../_images/8d97af721b4192937e801a32bfd579753e6a2e92fcbb26170d13780dc6eb9101.png ../../../_images/2e04b97c3fb471bcfc617b1621d57f31afa985e383ffa78e31a97d6ae134b253.png ../../../_images/4c460ccf9c305da8e9a98041b3f56028aa918182038c1fb1ff5f9458a37c16bb.png ../../../_images/c3266ae54cc7a1f19b6c44bc0fd19f82419f154860f655eb106a38f5cb06ebe3.png ../../../_images/d4ab4595128262aef09ffcbb2e1a69e8ea3d8c8c5496c3404f65484d1a891b22.png