Exemple #1
0
                           value)
from pyomo.util.check_units import assert_units_consistent

from idaes.generic_models.properties.tests.test_harness import \
    PropertyTestHarness
from idaes.core.util import get_solver


# Set module level pyest marker
pytestmark = pytest.mark.cubic_root
prop_available = cubic_roots_available()


# -----------------------------------------------------------------------------
# Get default solver for testing
solver = get_solver()


# -----------------------------------------------------------------------------
# Run test harness
@pytest.mark.unit
class TestBasicLV(PropertyTestHarness):
    def configure(self):
        self.prop_pack = BT_PR.BTParameterBlock
        self.param_args = {"valid_phase": ("Liq", "Vap")}
        self.prop_args = {}
        self.has_density_terms = True


@pytest.mark.unit
class TestBasicL(PropertyTestHarness):
Exemple #2
0
                                              number_variables,
                                              number_total_constraints,
                                              number_unused_variables)
from idaes.core.util.testing import (PhysicalParameterTestBlock,
                                     ReactionParameterTestBlock,
                                     initialization_tester)
from idaes.core.util import get_solver
from pyomo.util.check_units import (assert_units_consistent,
                                    assert_units_equivalent)

from idaes.generic_models.properties import iapws95
import idaes.core.util.scaling as iscale

# -----------------------------------------------------------------------------
# Get default solver for testing
solver = get_solver(options={"nlp_scaling_method": "user-scaling"})


class GenericValve(object):
    @pytest.fixture(scope="class")
    def valve_model(self):
        m = ConcreteModel()
        m.fs = FlowsheetBlock(default={"dynamic": False})
        m.fs.properties = iapws95.Iapws95ParameterBlock()
        m.fs.valve = Valve(
            default={
                "valve_function_callback": self.type,
                "property_package": m.fs.properties
            })
        fin = 1000  # mol/s
        pin = 200000  # Pa
Exemple #3
0
    def initialize(
        self,
        shell_state_args=None,
        tube_state_args=None,
        outlvl=idaeslog.NOTSET,
        solver=None,
        optarg=None,
    ):
        """
        Initialization routine for the unit.

        Keyword Arguments:
            state_args : a dict of arguments to be passed to the property
                         package(s) to provide an initial state for
                         initialization (see documentation of the specific
                         property package) (default = {}).
            outlvl : sets output level of initialization routine
            optarg : solver options dictionary object (default=None, use
                     default solver options)
            solver : str indicating which solver to use during
                     initialization (default = None, use default solver)

        Returns:
            None
        """
        init_log = idaeslog.getInitLogger(self.name, outlvl, tag="unit")
        solve_log = idaeslog.getSolveLogger(self.name, outlvl, tag="unit")

        # Create solver
        opt = get_solver(solver, optarg)

        # ---------------------------------------------------------------------
        # Initialize shell block
        flags_shell = self.shell.initialize(
            outlvl=outlvl,
            optarg=optarg,
            solver=solver,
            state_args=shell_state_args,
        )

        flags_tube = self.tube.initialize(
            outlvl=outlvl,
            optarg=optarg,
            solver=solver,
            state_args=tube_state_args,
        )

        init_log.info_high("Initialization Step 1 Complete.")

        # ---------------------------------------------------------------------
        # Solve unit
        # Wall 0D
        if self.config.has_wall_conduction == \
                WallConductionType.zero_dimensional:
            shell_units = self.config.shell_side.property_package.\
                get_metadata().get_derived_units
            for t in self.flowsheet().time:
                for z in self.shell.length_domain:
                    self.temperature_wall[t, z].fix(
                        value(
                            0.5
                            * (
                                self.shell.properties[t, 0].temperature
                                + pyunits.convert(
                                    self.tube.properties[t, 0].temperature,
                                    to_units=shell_units('temperature'))
                            )
                        )
                    )

            self.tube.deactivate()
            self.tube_heat_transfer_eq.deactivate()
            self.wall_0D_model.deactivate()

            with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
                res = opt.solve(self, tee=slc.tee)
            init_log.info_high(
                "Initialization Step 2 {}.".format(idaeslog.condition(res))
            )

            self.tube.activate()
            self.tube_heat_transfer_eq.activate()

            with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
                res = opt.solve(self, tee=slc.tee)
            init_log.info_high(
                "Initialization Step 3 {}.".format(idaeslog.condition(res))
            )

            self.wall_0D_model.activate()
            self.temperature_wall.unfix()

            with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
                res = opt.solve(self, tee=slc.tee)
            init_log.info_high(
                "Initialization Step 4 {}.".format(idaeslog.condition(res))
            )
        else:
            res = None

        self.shell.release_state(flags_shell)
        self.tube.release_state(flags_tube)

        if res is not None and not check_optimal_termination(res):
            raise InitializationError(
                f"{self.name} failed to initialize successfully. Please check "
                f"the output logs for more information.")

        init_log.info("Initialization Complete.")
    def initialize(blk, state_args={}, state_vars_fixed=False,
                   hold_state=False, outlvl=idaeslog.NOTSET,
                   solver=None, optarg=None):
        """
        Initialization routine for property package.
        Keyword Arguments:
            state_args : Dictionary with initial guesses for the state vars
                         chosen. The keys for the state_args dictionary are:

                         flow_mol : value at which to initialize flow rate
                         mole_frac_comp : dict of values to use when
                                          initializing mole fractions
                         pressure : value at which to initialize pressure
                         temperature : value at which to initialize temperature
            outlvl : sets logger output level for initialization routine
            optarg : solver options dictionary object (default=None)
            state_vars_fixed: Flag to denote if state vars have already been
                              fixed.
                              - True - states have already been fixed by the
                                       control volume 1D. Control volume 0D
                                       does not fix the state vars, so will
                                       be False if this state block is used
                                       with 0D blocks.
                             - False - states have not been fixed. The state
                                       block will deal with fixing/unfixing.
            solver : str indicating whcih solver to use during
                     initialization (default = None, use default solver)
            hold_state : flag indicating whether the initialization routine
                         should unfix any state variables fixed during
                         initialization (default=False).
                         - True - states varaibles are not unfixed, and
                                 a dict of returned containing flags for
                                 which states were fixed during
                                 initialization.
                        - False - state variables are unfixed after
                                 initialization by calling the
                                 relase_state method
        Returns:
            If hold_states is True, returns a dict containing flags for
            which states were fixed during initialization.
        """

        init_log = idaeslog.getInitLogger(blk.name, outlvl, tag="properties")
        solve_log = idaeslog.getSolveLogger(blk.name, outlvl, tag="properties")

        # Fix state variables if not already fixed
        if state_vars_fixed is False:
            flags = fix_state_vars(blk, state_args)

        else:
            pass

        # Deactivate sum of mole fractions constraint
        for k in blk.keys():
            if blk[k].config.defined_state is False:
                blk[k].mole_fraction_constraint.deactivate()

        # Check that degrees of freedom are zero after fixing state vars
        for k in blk.keys():
            if degrees_of_freedom(blk[k]) != 0:
                raise Exception("State vars fixed but degrees of freedom "
                                "for state block is not zero during "
                                "initialization.")

        # Set solver options
        if optarg is None:
            optarg = {"tol": 1e-8}

        opt = get_solver(solver, optarg)

        # ---------------------------------------------------------------------
        # Initialize property calculations

        # Check that there is something to solve for
        free_vars = 0
        for k in blk.keys():
            free_vars += number_unfixed_variables(blk[k])
        if free_vars > 0:
            # If there are free variables, call the solver to initialize
            try:
                with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
                    res = solve_indexed_blocks(opt, [blk], tee=slc.tee)
            except:
                res = None
        else:
            res = None

        init_log.info("Properties Initialized {}.".format(
            idaeslog.condition(res)))

        # ---------------------------------------------------------------------
        # Return state to initial conditions
        if state_vars_fixed is False:
            if hold_state is True:
                return flags
            else:
                blk.release_state(flags)

        init_log.info("Initialization Complete")
Exemple #5
0
    def test_solve_for_true_species(self, frame):
        m = frame

        m.fs.state[1].temperature.fix(350)
        m.fs.state[1].pressure.fix(1e5)

        m.fs.state[1].flow_mol_comp["H2O"].fix(0.8 * 2)
        m.fs.state[1].flow_mol_comp["K2CO3"].fix(0.2 * 2)
        m.fs.state[1].flow_mol_comp["KHCO3"].fix(0)
        m.fs.state[1].flow_mol_comp["KOH"].fix(0)

        assert degrees_of_freedom(m.fs) == 0

        m.fs.state.initialize()

        solver = get_solver()
        res = solver.solve(m.fs)

        # Check for optimal solution
        assert res.solver.termination_condition == \
            TerminationCondition.optimal
        assert res.solver.status == SolverStatus.ok

        # Check apparent species flowrates
        for j in m.fs.state[1].mole_frac_comp:
            assert (value(m.fs.state[1].flow_mol_phase_comp_apparent["Liq", j])
                    == pytest.approx(value(m.fs.state[1].flow_mol *
                                           m.fs.state[1].mole_frac_comp[j]),
                                     rel=1e-5))

        # Check element balances
        assert (value(
            m.fs.state[1].flow_mol_phase_comp_apparent["Liq", "K2CO3"] * 2 +
            m.fs.state[1].flow_mol_phase_comp_apparent["Liq", "KHCO3"] +
            m.fs.state[1].flow_mol_phase_comp_apparent["Liq", "KOH"]) ==
                pytest.approx(value(
                    m.fs.state[1].flow_mol_phase_comp_true["Liq", "K+"]),
                              rel=1e-5))
        assert (
            value(m.fs.state[1].flow_mol_phase_comp_apparent["Liq", "K2CO3"] +
                  m.fs.state[1].flow_mol_phase_comp_apparent["Liq", "KHCO3"])
            == pytest.approx(
                value(m.fs.state[1].flow_mol_phase_comp_true["Liq", "CO3--"] +
                      m.fs.state[1].flow_mol_phase_comp_true["Liq", "HCO3-"]),
                rel=1e-5))
        assert (value(
            m.fs.state[1].flow_mol_phase_comp_apparent["Liq", "K2CO3"] * 3 +
            m.fs.state[1].flow_mol_phase_comp_apparent["Liq", "KHCO3"] * 3 +
            m.fs.state[1].flow_mol_phase_comp_apparent["Liq", "KOH"] +
            m.fs.state[1].flow_mol_phase_comp_apparent["Liq", "H2O"]
        ) == pytest.approx(
            value(m.fs.state[1].flow_mol_phase_comp_true["Liq", "CO3--"] * 3 +
                  m.fs.state[1].flow_mol_phase_comp_true["Liq", "HCO3-"] * 3 +
                  m.fs.state[1].flow_mol_phase_comp_true["Liq", "OH-"] +
                  m.fs.state[1].flow_mol_phase_comp_true["Liq", "H2O"]),
            rel=1e-5))
        assert (value(
            m.fs.state[1].flow_mol_phase_comp_apparent["Liq", "KHCO3"] +
            m.fs.state[1].flow_mol_phase_comp_apparent["Liq", "KOH"] +
            m.fs.state[1].flow_mol_phase_comp_apparent["Liq", "H2O"] * 2
        ) == pytest.approx(
            value(m.fs.state[1].flow_mol_phase_comp_true["Liq", "HCO3-"] +
                  m.fs.state[1].flow_mol_phase_comp_true["Liq", "OH-"] +
                  m.fs.state[1].flow_mol_phase_comp_true["Liq", "H+"] +
                  m.fs.state[1].flow_mol_phase_comp_true["Liq", "H2O"] * 2),
            rel=1e-5))

        # Check true species mole fractions
        assert (value(
            m.fs.state[1].mole_frac_phase_comp_true["Liq",
                                                    "CO3--"]) == pytest.approx(
                                                        0.142857, rel=1e-5))
        assert (value(
            m.fs.state[1].mole_frac_phase_comp_true["Liq",
                                                    "H+"]) == pytest.approx(
                                                        2.90081e-16, rel=1e-5))
        assert (value(
            m.fs.state[1].mole_frac_phase_comp_true["Liq",
                                                    "H2O"]) == pytest.approx(
                                                        0.571429, rel=1e-5))
        assert (value(
            m.fs.state[1].mole_frac_phase_comp_true["Liq",
                                                    "HCO3-"]) == pytest.approx(
                                                        1.13961e-08, rel=1e-5))
        assert (value(
            m.fs.state[1].mole_frac_phase_comp_true["Liq",
                                                    "K+"]) == pytest.approx(
                                                        0.285714, rel=1e-5))
        assert (value(
            m.fs.state[1].mole_frac_phase_comp_true["Liq",
                                                    "OH-"]) == pytest.approx(
                                                        1.139606e-08,
                                                        rel=1e-5))
Exemple #6
0
    def initialize(self,
                   state_args={},
                   state_vars_fixed=False,
                   hold_state=False,
                   outlvl=idaeslog.NOTSET,
                   temperature_bounds=(260, 616),
                   solver=None,
                   optarg={'tol': 1e-8}):
        '''
        Initialization routine for property package.
        Keyword Arguments:
        state_args : Dictionary with initial guesses for the state vars
                     chosen. Note that if this method is triggered
                     through the control volume, and if initial guesses
                     were not provied at the unit model level, the
                     control volume passes the inlet values as initial
                     guess.The keys for the state_args dictionary are:
                     flow_mol_comp : value at which to initialize component
                                     flows (default=None)
                     pressure : value at which to initialize pressure
                                (default=None)
                     temperature : value at which to initialize temperature
                                  (default=None)
            outlvl : sets output level of initialization routine
            state_vars_fixed: Flag to denote if state vars have already been
                              fixed.
                              - True - states have already been fixed and
                                       initialization does not need to worry
                                       about fixing and unfixing variables.
                             - False - states have not been fixed. The state
                                       block will deal with fixing/unfixing.
            optarg : solver options dictionary object (default=None)
            solver : str indicating whcih solver to use during
                     initialization (default = 'ipopt')
            hold_state : flag indicating whether the initialization routine
                         should unfix any state variables fixed during
                         initialization (default=False).
                         - True - states varaibles are not unfixed, and
                                 a dict of returned containing flags for
                                 which states were fixed during
                                 initialization.
                        - False - state variables are unfixed after
                                 initialization by calling the
                                 relase_state method
        Returns:
            If hold_states is True, returns a dict containing flags for
            which states were fixed during initialization.
        '''
        init_log = idaeslog.getInitLogger(self.name, outlvl, tag="properties")
        solve_log = idaeslog.getSolveLogger(self.name,
                                            outlvl,
                                            tag="properties")

        if state_vars_fixed is False:
            # Fix state variables if not already fixed
            flags = fix_state_vars(self, state_args)

        else:
            # Check when the state vars are fixed already result in dof 0
            for k in self.keys():
                if degrees_of_freedom(self[k]) != 0:
                    raise Exception("State vars fixed but degrees of freedom "
                                    "for state block is not zero during "
                                    "initialization.")

        if optarg is None:
            sopt = {"tol": 1e-8}
        else:
            sopt = optarg

        # opt = SolverFactory(solver)
        opt = get_solver(solver, optarg)

        opt.options = sopt

        with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
            res = solve_indexed_blocks(opt, [self], tee=slc.tee)
        init_log.info("Initialization Step 1 {}.".format(
            idaeslog.condition(res)))

        if state_vars_fixed is False:
            if hold_state is True:
                return flags
            else:
                self.release_state(flags)

        init_log.info('Initialization Complete.')
Exemple #7
0
def initialize_by_time_element(fs, time, **kwargs):
    """
    Function to initialize Flowsheet fs element-by-element along 
    ContinuousSet time. Assumes sufficient initialization/correct degrees 
    of freedom such that the first finite element can be solved immediately 
    and each subsequent finite element can be solved by fixing differential
    and derivative variables at the initial time point of that finite element.

    Args:
        fs : Flowsheet to initialize
        time : Set whose elements will be solved for individually
        solver : Pyomo solver object initialized with user's desired options
        outlvl : IDAES logger outlvl
        ignore_dof : Bool. If True, checks for square problems will be skipped.

    Returns:
        None
    """
    if not isinstance(fs, FlowsheetBlock):
        raise TypeError('First arg must be a FlowsheetBlock')
    if not isinstance(time, ContinuousSet):
        raise TypeError('Second arg must be a ContinuousSet')

    if time.get_discretization_info() == {}:
        raise ValueError('ContinuousSet must be discretized')

    scheme = time.get_discretization_info()['scheme']
    fep_list = time.get_finite_elements()
    nfe = time.get_discretization_info()['nfe']

    if scheme == 'LAGRANGE-RADAU':
        ncp = time.get_discretization_info()['ncp']
    elif scheme == 'LAGRANGE-LEGENDRE':
        msg = 'Initialization does not support collocation with Legendre roots'
        raise NotImplementedError(msg)
    elif scheme == 'BACKWARD Difference':
        ncp = 1
    elif scheme == 'FORWARD Difference':
        ncp = 1
        msg = 'Forward initialization (explicit Euler) has not yet been implemented'
        raise NotImplementedError(msg)
    elif scheme == 'CENTRAL Difference':
        msg = 'Initialization does not support central finite difference'
        raise NotImplementedError(msg)
    else:
        msg = 'Unrecognized discretization scheme. '
        'Has the model been discretized along the provided ContinuousSet?'
        raise ValueError(msg)
    # Disallow Central/Legendre discretizations.
    # Neither of these seem to be square by default for multi-finite element
    # initial value problems.

    # Create logger objects
    outlvl = kwargs.pop('outlvl', idaeslog.NOTSET)
    init_log = idaeslog.getInitLogger(__name__, level=outlvl)
    solver_log = idaeslog.getSolveLogger(__name__, level=outlvl)

    ignore_dof = kwargs.pop('ignore_dof', False)
    solver = kwargs.pop('solver', get_solver())
    fix_diff_only = kwargs.pop('fix_diff_only', True)
    # This option makes the assumption that the only variables that
    # link constraints to previous points in time (which must be fixed)
    # are the derivatives and differential variables. Not true if a controller
    # is being present, but should be a good assumption otherwise, and is
    # significantly faster than searching each constraint for time-linking
    # variables.

    if not ignore_dof:
        if degrees_of_freedom(fs) != 0:
            msg = ('Original model has nonzero degrees of freedom. This was '
                   'unexpected. Use keyword arg igore_dof=True to skip this '
                   'check.')
            init_log.error(msg)
            raise ValueError('Nonzero degrees of freedom.')

    # Get dict telling which constraints/blocks are already inactive:
    # dict: id(compdata) -> bool (is active?)
    was_originally_active = get_activity_dict(fs)

    # Deactivate flowsheet except at t0, solve to ensure consistency
    # of initial conditions.
    non_initial_time = [t for t in time]
    non_initial_time.remove(time.first())
    deactivated = deactivate_model_at(fs,
                                      time,
                                      non_initial_time,
                                      outlvl=idaeslog.ERROR)

    if not ignore_dof:
        if degrees_of_freedom(fs) != 0:
            msg = (
                'Model has nonzero degrees of freedom at initial conditions.'
                ' This was unexpected. Use keyword arg igore_dof=True to skip'
                ' this check.')
            init_log.error(msg)
            raise ValueError('Nonzero degrees of freedom.')

    init_log.info(
        'Model is inactive except at t=0. Solving for consistent initial conditions.'
    )
    with idaeslog.solver_log(solver_log, level=idaeslog.DEBUG) as slc:
        results = solver.solve(fs, tee=slc.tee)
    if results.solver.termination_condition == TerminationCondition.optimal:
        init_log.info('Successfully solved for consistent initial conditions')
    else:
        init_log.error('Failed to solve for consistent initial conditions')
        raise ValueError('Solver failed in initialization')

    deactivated[time.first()] = deactivate_model_at(
        fs, time, time.first(), outlvl=idaeslog.ERROR)[time.first()]

    # Here, deactivate non-time-indexed components. Do this after solve
    # for initial conditions in case these were used to specify initial
    # conditions
    con_unindexed_by_time = deactivate_constraints_unindexed_by(fs, time)
    var_unindexed_by_time = fix_vars_unindexed_by(fs, time)

    # Now model is completely inactive

    # For each timestep, we need to
    # 1. Activate model at points we're solving for
    # 2. Fix initial conditions (differential variables at previous timestep)
    #    of finite element
    # 3. Solve the (now) square system
    # 4. Revert the model to its prior state

    # This will make use of the following dictionaries mapping
    # time points -> time derivatives and time-differential variables
    derivs_at_time = get_derivatives_at(fs, time, [t for t in time])
    dvars_at_time = {
        t: [
            d.parent_component().get_state_var()[d.index()]
            for d in derivs_at_time[t]
        ]
        for t in time
    }

    # Perform a solve for 1 -> nfe; i is the index of the finite element
    init_log.info(
        'Flowsheet has been deactivated. Beginning element-wise initialization'
    )
    for i in range(1, nfe + 1):
        t_prev = time[(i - 1) * ncp + 1]
        # Non-initial time points in the finite element:
        fe = [time[k] for k in range((i - 1) * ncp + 2, i * ncp + 2)]

        init_log.info(f'Entering step {i}/{nfe} of initialization')

        # Activate components of model that were active in the presumably
        # square original system
        for t in fe:
            for comp in deactivated[t]:
                if was_originally_active[id(comp)]:
                    comp.activate()

        # Get lists of derivative and differential variables
        # at initial time point of finite element
        init_deriv_list = derivs_at_time[t_prev]
        init_dvar_list = dvars_at_time[t_prev]

        # Variables that were originally fixed
        fixed_vars = []
        if fix_diff_only:
            for drv in init_deriv_list:
                # Cannot fix variables with value None.
                # Any variable with value None was not solved for
                # (either stale or not included in previous solve)
                # and we don't want to fix it.
                if not drv.fixed:
                    fixed_vars.append(drv)
                if not drv.value is None:
                    drv.fix()
            for dv in init_dvar_list:
                if not dv.fixed:
                    fixed_vars.append(dv)
                if not dv.value is None:
                    dv.fix()
        else:
            for con in fs.component_data_objects(Constraint, active=True):
                for var in identify_variables(con.expr, include_fixed=False):
                    t_idx = get_implicit_index_of_set(var, time)
                    if t_idx is None:
                        continue
                    if t_idx <= t_prev:
                        fixed_vars.append(var)
                        var.fix()

        # Initialize finite element from its initial conditions
        for t in fe:
            copy_values_at_time(fs,
                                fs,
                                t,
                                t_prev,
                                copy_fixed=False,
                                outlvl=idaeslog.ERROR)

        # Log that we are solving finite element {i}
        init_log.info(f'Solving finite element {i}')

        if not ignore_dof:
            if degrees_of_freedom(fs) != 0:
                msg = (
                    f'Model has nonzero degrees of freedom at finite element'
                    ' {i}. This was unexpected. '
                    'Use keyword arg igore_dof=True to skip this check.')
                init_log.error(msg)
                raise ValueError('Nonzero degrees of freedom')

        with idaeslog.solver_log(solver_log, level=idaeslog.DEBUG) as slc:
            results = solver.solve(fs, tee=slc.tee)
        if results.solver.termination_condition == TerminationCondition.optimal:
            init_log.info(f'Successfully solved finite element {i}')
        else:
            init_log.error(f'Failed to solve finite element {i}')
            raise ValueError('Failure in initialization solve')

        # Deactivate components that may have been activated
        for t in fe:
            for comp in deactivated[t]:
                comp.deactivate()

        # Unfix variables that have been fixed
        for var in fixed_vars:
            var.unfix()

        # Log that initialization step {i} has been finished
        init_log.info(f'Initialization step {i} complete')

    # Reactivate components of the model that were originally active
    for t in time:
        for comp in deactivated[t]:
            if was_originally_active[id(comp)]:
                comp.activate()

    for con in con_unindexed_by_time:
        con.activate()
    for var in var_unindexed_by_time:
        var.unfix()

    # Logger message that initialization is finished
    init_log.info('Initialization completed. Model has been reactivated')
    def initialize(
        self,
        state_args=None,
        state_vars_fixed=False,
        hold_state=False,
        outlvl=idaeslog.NOTSET,
        solver=None,
        optarg=None,
    ):
        """
        Initialization routine for property package.
        Keyword Arguments:
            state_args : Dictionary with initial guesses for the state vars
                         chosen. Note that if this method is triggered
                         through the control volume, and if initial guesses
                         were not provided at the unit model level, the
                         control volume passes the inlet values as initial
                         guess.The keys for the state_args dictionary are:

                         flow_mass_phase_comp : value at which to initialize
                                               phase component flows
                         pressure : value at which to initialize pressure
                         temperature : value at which to initialize temperature
            outlvl : sets output level of initialization routine (default=idaeslog.NOTSET)
            optarg : solver options dictionary object (default=None)
            state_vars_fixed: Flag to denote if state vars have already been
                              fixed.
                              - True - states have already been fixed by the
                                       control volume 1D. Control volume 0D
                                       does not fix the state vars, so will
                                       be False if this state block is used
                                       with 0D blocks.
                             - False - states have not been fixed. The state
                                       block will deal with fixing/unfixing.
            solver : Solver object to use during initialization if None is provided
                     it will use the default solver for IDAES (default = None)
            hold_state : flag indicating whether the initialization routine
                         should unfix any state variables fixed during
                         initialization (default=False).
                         - True - states variables are not unfixed, and
                                 a dict of returned containing flags for
                                 which states were fixed during
                                 initialization.
                        - False - state variables are unfixed after
                                 initialization by calling the
                                 release_state method
        Returns:
            If hold_states is True, returns a dict containing flags for
            which states were fixed during initialization.
        """
        # Get loggers
        init_log = idaeslog.getInitLogger(self.name, outlvl, tag="properties")
        solve_log = idaeslog.getSolveLogger(self.name, outlvl, tag="properties")

        # Set solver and options
        opt = get_solver(solver, optarg)

        # Fix state variables
        flags = fix_state_vars(self, state_args)
        # Check when the state vars are fixed already result in dof 0
        for k in self.keys():
            dof = degrees_of_freedom(self[k])
            if dof != 0:
                raise PropertyPackageError(
                    "\nWhile initializing {sb_name}, the degrees of freedom "
                    "are {dof}, when zero is required. \nInitialization assumes "
                    "that the state variables should be fixed and that no other "
                    "variables are fixed. \nIf other properties have a "
                    "predetermined value, use the calculate_state method "
                    "before using initialize to determine the values for "
                    "the state variables and avoid fixing the property variables."
                    "".format(sb_name=self.name, dof=dof)
                )

        # ---------------------------------------------------------------------
        skip_solve = True  # skip solve if only state variables are present
        for k in self.keys():
            if number_unfixed_variables(self[k]) != 0:
                skip_solve = False

        if not skip_solve:
            # Initialize properties
            with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
                results = solve_indexed_blocks(opt, [self], tee=slc.tee)
            init_log.info_high(
                "Property initialization: {}.".format(idaeslog.condition(results))
            )

            if not check_optimal_termination(results):
                raise InitializationError(
                    f"{self.name} failed to initialize successfully. Please "
                    f"check the output logs for more information."
                )

        # ---------------------------------------------------------------------
        # If input block, return flags, else release state
        if state_vars_fixed is False:
            if hold_state is True:
                return flags
            else:
                self.release_state(flags)
    def calculate_state(
        self,
        var_args=None,
        hold_state=False,
        outlvl=idaeslog.NOTSET,
        solver=None,
        optarg=None,
    ):
        """
        Solves state blocks given a set of variables and their values. These variables can
        be state variables or properties. This method is typically used before
        initialization to solve for state variables because non-state variables (i.e. properties)
        cannot be fixed in initialization routines.

        Keyword Arguments:
            var_args : dictionary with variables and their values, they can be state variables or properties
                       {(VAR_NAME, INDEX): VALUE}
            hold_state : flag indicating whether all of the state variables should be fixed after calculate state.
                         True - State variables will be fixed.
                         False - State variables will remain unfixed, unless already fixed.
            outlvl : idaes logger object that sets output level of solve call (default=idaeslog.NOTSET)
            solver : solver name string if None is provided the default solver
                     for IDAES will be used (default = None)
            optarg : solver options dictionary object (default={})

        Returns:
            results object from state block solve
        """
        # Get logger
        solve_log = idaeslog.getSolveLogger(self.name, level=outlvl, tag="properties")

        # Initialize at current state values (not user provided)
        self.initialize(solver=solver, optarg=optarg, outlvl=outlvl)

        # Set solver and options
        opt = get_solver(solver, optarg)

        # Fix variables and check degrees of freedom
        flags = (
            {}
        )  # dictionary noting which variables were fixed and their previous state
        for k in self.keys():
            sb = self[k]
            for (v_name, ind), val in var_args.items():
                var = getattr(sb, v_name)
                if iscale.get_scaling_factor(var[ind]) is None:
                    _log.warning(
                        "While using the calculate_state method on {sb_name}, variable {v_name} "
                        "was provided as an argument in var_args, but it does not have a scaling "
                        "factor. This suggests that the calculate_scaling_factor method has not been "
                        "used or the variable was created on demand after the scaling factors were "
                        "calculated. It is recommended to touch all relevant variables (i.e. call "
                        "them or set an initial value) before using the calculate_scaling_factor "
                        "method.".format(v_name=v_name, sb_name=sb.name)
                    )
                if var[ind].is_fixed():
                    flags[(k, v_name, ind)] = True
                    if value(var[ind]) != val:
                        raise ConfigurationError(
                            "While using the calculate_state method on {sb_name}, {v_name} was "
                            "fixed to a value {val}, but it was already fixed to value {val_2}. "
                            "Unfix the variable before calling the calculate_state "
                            "method or update var_args."
                            "".format(
                                sb_name=sb.name,
                                v_name=var.name,
                                val=val,
                                val_2=value(var[ind]),
                            )
                        )
                else:
                    flags[(k, v_name, ind)] = False
                    var[ind].fix(val)

            if degrees_of_freedom(sb) != 0:
                raise RuntimeError(
                    "While using the calculate_state method on {sb_name}, the degrees "
                    "of freedom were {dof}, but 0 is required. Check var_args and ensure "
                    "the correct fixed variables are provided."
                    "".format(sb_name=sb.name, dof=degrees_of_freedom(sb))
                )

        # Solve
        with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
            results = solve_indexed_blocks(opt, [self], tee=slc.tee)
            solve_log.info_high(
                "Calculate state: {}.".format(idaeslog.condition(results))
            )

        if not check_optimal_termination(results):
            _log.warning(
                "While using the calculate_state method on {sb_name}, the solver failed "
                "to converge to an optimal solution. This suggests that the user provided "
                "infeasible inputs, or that the model is poorly scaled, poorly initialized, "
                "or degenerate."
            )

        # unfix all variables fixed with var_args
        for (k, v_name, ind), previously_fixed in flags.items():
            if not previously_fixed:
                var = getattr(self[k], v_name)
                var[ind].unfix()

        # fix state variables if hold_state
        if hold_state:
            fix_state_vars(self)

        return results
Exemple #10
0
    def initialize(self, *args, **kwargs):
        outlvl = kwargs.get("outlvl", idaeslog.NOTSET)

        init_log = idaeslog.getInitLogger(self.name, outlvl, tag="unit")
        solve_log = idaeslog.getSolveLogger(self.name, outlvl, tag="unit")

        config = self.config  # shorter ref to config for less line splitting
        sp = StoreSpec.value_isfixed_isactive(only_fixed=True)
        istate = to_json(self, return_dict=True, wts=sp)

        # the initialization here isn't straight forward since
        # the heat exchanger may have 3 stages and they are countercurrent.
        # For simplicity each stage in initialized with the same cooling water
        # inlet conditions then the whole feedwater heater is solved together.
        # There are more robust aproaches which can be implimented if needed.

        # initialize desuperheat if any
        if config.has_desuperheat:
            if config.has_drain_cooling:
                _set_port(self.desuperheat.inlet_2, self.cooling.inlet_2)
            else:
                _set_port(self.desuperheat.inlet_2, self.condense.inlet_2)
            self.desuperheat.initialize(*args, **kwargs)
            self.desuperheat.inlet_1.flow_mol.unfix()
            if config.has_drain_mixer:
                _set_port(self.drain_mix.steam, self.desuperheat.outlet_1)
            else:
                _set_port(self.condense.inlet_1, self.desuperheat.outlet_1)
            # fix the steam and fwh inlet for init
            self.desuperheat.inlet_1.fix()
            self.desuperheat.inlet_1.flow_mol.unfix()  # unfix for extract calc
        # initialize mixer if included
        if config.has_drain_mixer:
            self.drain_mix.steam.fix()
            self.drain_mix.drain.fix()
            self.drain_mix.outlet.unfix()
            self.drain_mix.initialize(*args, **kwargs)
            _set_port(self.condense.inlet_1, self.drain_mix.outlet)
            if config.has_desuperheat:
                self.drain_mix.steam.unfix()
            else:
                self.drain_mix.steam.flow_mol.unfix()
        # Initialize condense section
        if config.has_drain_cooling:
            _set_port(self.condense.inlet_2, self.cooling.inlet_2)
            self.cooling.inlet_2.fix()
        else:
            self.condense.inlet_2.fix()
        if not config.has_drain_mixer and not config.has_desuperheat:
            self.condense.inlet_1.fix()
            self.condense.inlet_1.flow_mol.unfix()

        tempsat = value(self.condense.shell.properties_in[0].temperature_sat)
        temp = value(self.condense.tube.properties_in[0].temperature)
        if tempsat - temp < 30:
            init_log.warning(
                "The steam sat. temperature ({}) is near the feedwater"
                " inlet temperature ({})".format(tempsat, temp)
            )

        self.condense.initialize()
        # Initialize drain cooling if included
        if config.has_drain_cooling:
            _set_port(self.cooling.inlet_1, self.condense.outlet_1)
            self.cooling.initialize(*args, **kwargs)

        # Create solver
        opt = get_solver(kwargs.get("solver"), kwargs.get("oparg", {}))

        assert degrees_of_freedom(self) == 0
        with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
            res = opt.solve(self, tee=slc.tee)
        init_log.info(
            "Condensing shell inlet delta T = {}".format(
                value(self.condense.delta_temperature_in[0])
            )
        )
        init_log.info(
            "Condensing Shell outlet delta T = {}".format(
                value(self.condense.delta_temperature_out[0])
            )
        )
        init_log.info(
            "Steam Flow = {}".format(value(self.condense.inlet_1.flow_mol[0]))
        )
        init_log.info(
            "Initialization Complete: {}".format(idaeslog.condition(res))
        )

        from_json(self, sd=istate, wts=sp)
    def initialize_build(blk,
                         state_args=None,
                         outlvl=idaeslog.NOTSET,
                         solver=None,
                         optarg=None):
        """
        General wrapper for pressure changer initialization routines

        Keyword Arguments:
            state_args : a dict of arguments to be passed to the property
                         package(s) to provide an initial state for
                         initialization (see documentation of the specific
                         property package) (default = {}).
            outlvl : sets output level of initialization routine
            optarg : solver options dictionary object (default=None)
            solver : str indicating which solver to use during
                     initialization (default = None)

        Returns: None
        """
        init_log = idaeslog.getInitLogger(blk.name, outlvl, tag="unit")
        solve_log = idaeslog.getSolveLogger(blk.name, outlvl, tag="unit")
        # Set solver options
        opt = get_solver(solver, optarg)

        # ---------------------------------------------------------------------
        # Initialize holdup block
        flags = blk.feed_side.initialize(
            outlvl=outlvl,
            optarg=optarg,
            solver=solver,
            state_args=state_args,
        )
        init_log.info_high("Initialization Step 1 Complete.")
        # ---------------------------------------------------------------------
        # Initialize permeate
        # Set state_args from inlet state
        if state_args is None:
            state_args = {}
            state_dict = blk.feed_side.properties_in[
                blk.flowsheet().config.time.first()].define_port_members()

            for k in state_dict.keys():
                if state_dict[k].is_indexed():
                    state_args[k] = {}
                    for m in state_dict[k].keys():
                        state_args[k][m] = state_dict[k][m].value
                else:
                    state_args[k] = state_dict[k].value

        blk.properties_permeate.initialize(
            outlvl=outlvl,
            optarg=optarg,
            solver=solver,
            state_args=state_args,
        )
        init_log.info_high("Initialization Step 2 Complete.")

        # ---------------------------------------------------------------------
        # Solve unit
        with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
            res = opt.solve(blk, tee=slc.tee)
        init_log.info_high("Initialization Step 3 {}.".format(
            idaeslog.condition(res)))

        # ---------------------------------------------------------------------
        # Release Inlet state
        blk.feed_side.release_state(flags, outlvl + 1)
        init_log.info("Initialization Complete: {}".format(
            idaeslog.condition(res)))
Exemple #12
0
    def initialize(blk,
                   state_args=None,
                   hold_state=False,
                   state_vars_fixed=False,
                   outlvl=idaeslog.NOTSET,
                   solver=None,
                   optarg={}):
        """
        Initialization routine for property package.
        Keyword Arguments:
            state_args : Dictionary with initial guesses for the state vars
                         chosen. Note that if this method is triggered
                         through the control volume, and if initial guesses
                         were not provided at the unit model level, the
                         control volume passes the inlet values as initial
                         guess.
                         Keys for the state_args dictionary are:
                         flow_mass, temperature, and mass_frac_comp
            outlvl : sets output level of initialization routine
            optarg : solver options dictionary object (default={})
            solver : str indicating whcih solver to use during
                     initialization (default = None, use default solver)
            hold_state : flag indicating whether the initialization routine
                         should unfix any state variables fixed during
                         initialization (default=False).
                         - True - states varaibles are not unfixed, and
                                 a dict of returned containing flags for
                                 which states were fixed during
                                 initialization.
                        - False - state variables are unfixed after
                                 initialization by calling the
                                 relase_state method
        Returns:
            If hold_states is True, returns a dict containing flags for
            which states were fixed during initialization.
        """
        init_log = idaeslog.getInitLogger(blk.name, outlvl, tag="properties")
        solve_log = idaeslog.getSolveLogger(blk.name, outlvl, tag="properties")

        init_log.info_high('Starting initialization')

        # Deactivate the constraints specific for outlet block i.e.
        # when defined state is False
        for k in blk.keys():
            if blk[k].config.defined_state is False:
                blk[k].sum_component_eqn.deactivate()

        # Fix state variables if not already fixed
        if state_vars_fixed is False:
            flags = fix_state_vars(blk, state_args)
        else:
            # Check when the state vars are fixed already result in dof 0
            for k in blk.keys():
                if degrees_of_freedom(blk[k]) != 0:
                    raise Exception("State vars fixed but degrees of freedom "
                                    "for state block is not zero during "
                                    "initialization.")

        # Create solver
        opt = get_solver(solver, optarg)

        # ---------------------------------------------------------------------
        # Initialise values
        for k in blk.keys():
            if hasattr(blk[k], "density_skeletal_constraint"):
                calculate_variable_from_constraint(
                    blk[k].dens_mass_skeletal,
                    blk[k].density_skeletal_constraint)

            if hasattr(blk[k], "mixture_heat_capacity_eqn"):
                calculate_variable_from_constraint(
                    blk[k].cp_mass, blk[k].mixture_heat_capacity_eqn)

            if hasattr(blk[k], "mixture_enthalpy_eqn"):
                calculate_variable_from_constraint(blk[k].enth_mass,
                                                   blk[k].mixture_enthalpy_eqn)

            for j in blk[k]._params.component_list:

                if hasattr(blk[k], "cp_shomate_eqn"):
                    calculate_variable_from_constraint(
                        blk[k].cp_mol_comp[j], blk[k].cp_shomate_eqn[j])

                if hasattr(blk[k], "enthalpy_shomate_eqn"):
                    calculate_variable_from_constraint(
                        blk[k].enth_mol_comp[j],
                        blk[k].enthalpy_shomate_eqn[j])

        # Solve property block if non-empty
        free_vars = 0
        for k in blk.keys():
            free_vars += number_unfixed_variables_in_activated_equalities(
                blk[k])

        if free_vars > 0:
            with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
                res = solve_indexed_blocks(opt, [blk], tee=slc.tee)
        else:
            res = ""
        init_log.info_high("Initialization complete {}.".format(
            idaeslog.condition(res)))

        # ---------------------------------------------------------------------
        if state_vars_fixed is False:
            if hold_state is True:
                return flags
            else:
                blk.release_state(flags)
Exemple #13
0
                "reaction_order": {
                    ("Liq", "HOCl"): -1,
                    ("Liq", "H_+"): 1,
                    ("Liq", "OCl_-"): 1
                }
            }
            # End parameter_data
        }
        # End R2
    }
    # End equilibrium_reactions
}
# End reaction_config definition

# Get default solver for testing
solver = get_solver(options={"tol": 1e-11})


def build_ideal_naocl_prop(model):
    model.fs.ideal_naocl_thermo_params = GenericParameterBlock(
        default=ideal_naocl_thermo_config)
    model.fs.ideal_naocl_rxn_params = GenericReactionParameterBlock(
        default={
            "property_package": model.fs.ideal_naocl_thermo_params,
            **ideal_naocl_reaction_config
        })


def build_ideal_naocl_mixer_unit(model):
    model.fs.ideal_naocl_mixer_unit = Mixer(
        default={
    def initialize(blk, liquid_state_args=None, vapor_state_args=None,
                   outlvl=idaeslog.NOTSET, solver=None, optarg=None):
        '''
        Initialization routine for solvent reboiler unit model.

        Keyword Arguments:
            liquid_state_args : a dict of arguments to be passed to the
                liquid property packages to provide an initial state for
                initialization (see documentation of the specific property
                package) (default = none).
            vapor_state_args : a dict of arguments to be passed to the
                vapor property package to provide an initial state for
                initialization (see documentation of the specific property
                package) (default = none).
            outlvl : sets output level of initialization routine
            optarg : solver options dictionary object (default=None, use
                     default solver options)
            solver : str indicating which solver to use during
                     initialization (default = None, use default IDAES solver)

        Returns:
            None
        '''
        if optarg is None:
            optarg = {}

        # Check DOF
        if degrees_of_freedom(blk) != 0:
            raise ConfigurationError(
                f"{blk.name} degrees of freedom were not 0 at the beginning "
                f"of initialization. DoF = {degrees_of_freedom(blk)}")

        # Set solver options
        init_log = idaeslog.getInitLogger(blk.name, outlvl, tag="unit")
        solve_log = idaeslog.getSolveLogger(blk.name, outlvl, tag="unit")

        solverobj = get_solver(solver, optarg)

        # ---------------------------------------------------------------------
        # Initialize liquid phase control volume block
        flags = blk.liquid_phase.initialize(
            outlvl=outlvl,
            optarg=optarg,
            solver=solver,
            state_args=liquid_state_args,
            hold_state=True
        )

        init_log.info_high('Initialization Step 1 Complete.')
        # ---------------------------------------------------------------------
        # Initialize vapor phase state block
        if vapor_state_args is None:
            t_init = blk.flowsheet().time.first()
            vapor_state_args = {}
            vap_state_vars = blk.vapor_phase[t_init].define_state_vars()

            liq_state = blk.liquid_phase.properties_out[t_init]

            # Check for unindexed state variables
            for sv in vap_state_vars:
                if "flow" in sv:
                    # Flow varaible, assume 10% vaporization
                    if "phase_comp" in sv:
                        # Flow is indexed by phase and component
                        vapor_state_args[sv] = {}
                        for p, j in vap_state_vars[sv]:
                            if j in liq_state.component_list:
                                vapor_state_args[sv][p, j] = 0.1*value(
                                    getattr(liq_state, sv)[p, j])
                            else:
                                vapor_state_args[sv][p, j] = 1e-8
                    elif "comp" in sv:
                        # Flow is indexed by component
                        vapor_state_args[sv] = {}
                        for j in vap_state_vars[sv]:
                            if j in liq_state.component_list:
                                vapor_state_args[sv][j] = 0.1*value(
                                    getattr(liq_state, sv)[j])
                            else:
                                vapor_state_args[sv][j] = 1e-8
                    elif "phase" in sv:
                        # Flow is indexed by phase
                        vapor_state_args[sv] = {}
                        for p in vap_state_vars[sv]:
                            vapor_state_args[sv][p] = 0.1*value(
                                    getattr(liq_state, sv)["Liq"])
                    else:
                        vapor_state_args[sv] = 0.1*value(
                            getattr(liq_state, sv))
                elif "mole_frac" in sv:
                    vapor_state_args[sv] = {}
                    if "phase" in sv:
                        # Variable is indexed by phase and component
                        for p, j in vap_state_vars[sv].keys():
                            if j in liq_state.component_list:
                                vapor_state_args[sv][p, j] = value(
                                    liq_state.fug_phase_comp["Liq", j] /
                                    liq_state.pressure)
                            else:
                                vapor_state_args[sv][p, j] = 1e-8
                    else:
                        for j in vap_state_vars[sv].keys():
                            if j in liq_state.component_list:
                                vapor_state_args[sv][j] = value(
                                    liq_state.fug_phase_comp["Liq", j] /
                                    liq_state.pressure)
                            else:
                                vapor_state_args[sv][j] = 1e-8
                else:
                    vapor_state_args[sv] = value(
                        getattr(liq_state, sv))

        blk.vapor_phase.initialize(
            outlvl=outlvl,
            optarg=optarg,
            solver=solver,
            state_args=vapor_state_args,
            hold_state=False
        )

        init_log.info_high('Initialization Step 2 Complete.')
        # ---------------------------------------------------------------------
        # Solve unit model
        with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
            results = solverobj.solve(blk, tee=slc.tee)

        init_log.info_high(
            "Initialization Step 3 {}.".format(idaeslog.condition(results))
        )

        # ---------------------------------------------------------------------
        # Release Inlet state
        blk.liquid_phase.release_state(flags, outlvl)

        init_log.info('Initialization Complete: {}'
                      .format(idaeslog.condition(results)))
Exemple #15
0
    def initialize(self,
                   state_args=None,
                   outlvl=idaeslog.NOTSET,
                   solver=None,
                   optarg=None):
        """
        Initialize the inlet compressor stage model.
        This deactivates the specialized constraints,
        then does the isentropic compressor initialization,
        then reactivates the constraints and solves.

        Args:
            state_args (dict): Initial state for property initialization
            outlvl: Initialization logger level
            solver (str): Solver to use for initialization
            optarg (dict): Solver arguments dictionary
        """
        init_log = idaeslog.getInitLogger(self.name, outlvl, tag="unit")
        solve_log = idaeslog.getSolveLogger(self.name, outlvl, tag="unit")

        # Create solver
        opt = get_solver(solver, optarg)

        unfix_ratioP = {}
        for t in self.flowsheet().time:
            # if there is not a good guess for efficiency or outlet pressure
            # provide something reasonable.
            eff = self.efficiency_isentropic[t]
            eff.fix(eff.value
                    if pyo.value(eff) > 0.3 and pyo.value(eff) < 1.0 else 0.85)
            # check for alternate pressure specs
            if self.outlet.pressure[t].fixed:
                self.ratioP[t] = pyo.value(self.outlet.pressure[t] /
                                           self.inlet.pressure[t])
            elif self.control_volume.deltaP[t].fixed:
                self.ratioP[t] = pyo.value(
                    (self.control_volume.deltaP[t] + self.inlet.pressure[t]) /
                    self.inlet.pressure[t])
            elif self.ratioP[t].fixed:
                self.outlet.pressure[t] = pyo.value(self.ratioP[t] *
                                                    self.inlet.pressure[t])
            else:
                if value(self.ratioP[t]) is None or value(
                        self.ratioP[t]) < 1.01:
                    self.ratioP[t].fix(1.5)
                else:
                    self.ratioP[t].fix()
                unfix_ratioP[t] = True

        # set list of constraints
        constraint_list = [
            "impeller_work_coeff_eqn",
            "polytropic_head_coeff_vaned_diffuser_eqn",
            "polytropic_head_coeff_eqn", "polytropic_efficiency_eqn", "Ma_con",
            "rspeed_con", "eff_p_v_cons", "polytropic_correlation",
            "delta_enth_polytropic_con", "mass_flow_coeff_eqn", "psi_3_eqn",
            "psi_s_eqn"
        ]

        # deactivate unit model level constraints
        for c in constraint_list:
            self.component(c).deactivate()

        super().initialize(state_args=state_args,
                           outlvl=outlvl,
                           solver=solver,
                           optarg=optarg)

        self.efficiency_isentropic.unfix()
        for t in self.flowsheet().time:
            if unfix_ratioP.get(t, False):
                self.ratioP[t].unfix()
        # Activate special constraints
        for c in constraint_list:
            getattr(self, c).activate()

        with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
            res = opt.solve(self, tee=slc.tee)
        init_log.info("Initialization Complete: {}".format(
            idaeslog.condition(res)))
Exemple #16
0
    def initialize(blk,
                   hotside_state_args=None,
                   coldside_state_args=None,
                   outlvl=idaeslog.NOTSET,
                   solver=None,
                   optarg={}):
        '''
        Initialisation routine for PHE unit (default solver ipopt)

        Keyword Arguments:
            state_args : a dict of arguments to be passed to the property
                           package(s) to provide an initial state for
                           initialization (see documentation of the specific
                           property package) (default = {}).
            outlvl : sets output level of initialization routine
            optarg : solver options dictionary object (default={})
            solver : str indicating whcih solver to use during
                     initialization (default = None)
        Returns:
            None
        '''
        # Set solver options
        init_log = idaeslog.getInitLogger(blk.name, outlvl, tag='unit')
        solve_log = idaeslog.getSolveLogger(blk.name, outlvl, tag="unit")

        # Create solver
        opt = get_solver(solver, optarg)

        hotside_state_args = {
            'flow_mol': value(blk.hot_inlet.flow_mol[0]),
            'temperature': value(blk.hot_inlet.temperature[0]),
            'pressure': value(blk.hot_inlet.pressure[0]),
            'mole_frac_comp': {
                'H2O': value(blk.hot_inlet.mole_frac_comp[0, 'H2O']),
                'CO2': value(blk.hot_inlet.mole_frac_comp[0, 'CO2']),
                'MEA': value(blk.hot_inlet.mole_frac_comp[0, 'MEA'])
            }
        }

        coldside_state_args = {
            'flow_mol': value(blk.cold_inlet.flow_mol[0]),
            'temperature': value(blk.cold_inlet.temperature[0]),
            'pressure': value(blk.cold_inlet.pressure[0]),
            'mole_frac_comp': {
                'H2O': value(blk.cold_inlet.mole_frac_comp[0, 'H2O']),
                'CO2': value(blk.cold_inlet.mole_frac_comp[0, 'CO2']),
                'MEA': value(blk.cold_inlet.mole_frac_comp[0, 'MEA'])
            }
        }

        # ---------------------------------------------------------------------
        # Initialize the INLET properties
        init_log.info('STEP 1: PROPERTY INITIALIZATION')
        init_log.info_high("INLET Properties initialization")
        blk.hot_side.properties_in.initialize(state_args=hotside_state_args,
                                              outlvl=outlvl,
                                              optarg=optarg,
                                              solver=solver,
                                              hold_state=True)
        blk.cold_side.properties_in.initialize(state_args=coldside_state_args,
                                               outlvl=outlvl,
                                               optarg=optarg,
                                               solver=solver,
                                               hold_state=True)

        # Initialize the OUTLET properties
        init_log.info_high("OUTLET Properties initialization")
        blk.hot_side.properties_out.initialize(state_args=hotside_state_args,
                                               outlvl=outlvl,
                                               optarg=optarg,
                                               solver=solver,
                                               hold_state=False)

        blk.cold_side.properties_out.initialize(state_args=coldside_state_args,
                                                outlvl=outlvl,
                                                optarg=optarg,
                                                solver=solver,
                                                hold_state=False)
        # ----------------------------------------------------------------------
        init_log.info('STEP 2: PHE INITIALIZATION')
        with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
            res = opt.solve(blk, tee=slc.tee)
        init_log.info_high("STEP 2 Complete: {}.".format(
            idaeslog.condition(res)))
        init_log.info('INITIALIZATION COMPLETED')