Beispiel #1
0
    def initialize(self,
                   state_args=None,
                   solver=None,
                   optarg=None,
                   outlvl=idaeslog.NOTSET):

        # TODO: Fix the inlets to the condenser to the vapor flow from
        # the top tray or take it as an argument to this method.

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

        if self.config.temperature_spec == TemperatureSpec.customTemperature:
            if degrees_of_freedom(self) != 0:
                raise ConfigurationError(
                    "Degrees of freedom is not 0 during initialization. "
                    "Check if outlet temperature has been fixed in addition "
                    "to the other inputs required as customTemperature was "
                    "selected for temperature_spec config argument.")

        if solver is None:
            init_log.warning("Solver not provided. Default solver(ipopt) "
                             " being used for initialization.")
            solver = get_default_solver()

        if state_args is None:
            state_args = {}
            state_dict = (self.control_volume.properties_in[
                self.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] = value(state_dict[k][m])
                else:
                    state_args[k] = value(state_dict[k])

        if self.config.condenser_type == CondenserType.totalCondenser:
            self.eq_total_cond_spec.deactivate()

        # Initialize the inlet and outlet state blocks
        flags = self.control_volume.initialize(state_args=state_args,
                                               solver=solver,
                                               optarg=optarg,
                                               outlvl=outlvl,
                                               hold_state=True)

        # Activate the total condenser spec
        if self.config.condenser_type == CondenserType.totalCondenser:
            self.eq_total_cond_spec.activate()

        with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
            res = solver.solve(self, tee=slc.tee)
        init_log.info("Initialization Complete, {}.".format(
            idaeslog.condition(res)))

        self.control_volume.release_state(flags=flags)
Beispiel #2
0
                                              fixed_variables_set,
                                              activated_constraints_set)
from idaes.core.util import get_default_solver

from idaes.generic_models.properties.core.generic.generic_property import (
    GenericParameterBlock)

from idaes.generic_models.properties.core.state_definitions import FTPx
from idaes.generic_models.properties.core.phase_equil import SmoothVLE

from idaes.generic_models.properties.core.examples.BT_ideal \
    import configuration

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


class TestParamBlock(object):
    @pytest.mark.unit
    def test_build(self):
        model = ConcreteModel()
        model.params = GenericParameterBlock(default=configuration)

        assert isinstance(model.params.phase_list, Set)
        assert len(model.params.phase_list) == 2
        for i in model.params.phase_list:
            assert i in ["Liq", "Vap"]
        assert model.params.Liq.is_liquid_phase()
        assert model.params.Vap.is_vapor_phase()
def solve_flowsheet(m, stee=False):
    solver = get_default_solver()
    solver.solve(m, tee=stee)
Beispiel #4
0
    def initialize(self,
                   state_args=None,
                   solver=None,
                   optarg=None,
                   outlvl=idaeslog.NOTSET):

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

        if solver is None:
            init_log.warning("Solver not provided. Default solver(ipopt) "
                             " being used for initialization.")
            solver = get_default_solver()

        # Initialize the inlet and outlet state blocks. Calling the state
        # blocks initialize methods directly so that custom set of state args
        # can be passed to the inlet and outlet state blocks as control_volume
        # initialize method initializes the state blocks with the same
        # state conditions.
        flags = self.control_volume.properties_in. \
            initialize(state_args=state_args,
                       solver=solver,
                       optarg=optarg,
                       outlvl=outlvl,
                       hold_state=True)

        # Initialize outlet state block at same conditions of inlet except
        # the temperature. Set the temperature to a temperature guess based
        # on the desired boilup_ratio.

        # Get index for bubble point temperature and and assume it
        # will have only a single phase equilibrium pair. This is to
        # support the generic property framework where the T_bubble
        # is indexed by the phases_in_equilibrium. In distillation,
        # the assumption is that there will only be a single pair
        # i.e. vap-liq.
        idx = next(
            iter(self.control_volume.properties_in[0].temperature_bubble))
        temp_guess = 0.5 * (
            value(self.control_volume.properties_in[0].temperature_dew[idx]) -
            value(self.control_volume.properties_in[0].
                  temperature_bubble[idx])) + \
            value(self.control_volume.properties_in[0].temperature_bubble[idx])

        state_args_outlet = {}
        state_dict_outlet = (self.control_volume.properties_in[
            self.flowsheet().config.time.first()].define_port_members())

        for k in state_dict_outlet.keys():
            if state_dict_outlet[k].is_indexed():
                state_args_outlet[k] = {}
                for m in state_dict_outlet[k].keys():
                    state_args_outlet[k][m] = value(state_dict_outlet[k][m])
            else:
                if k != "temperature":
                    state_args_outlet[k] = value(state_dict_outlet[k])
                else:
                    state_args_outlet[k] = temp_guess

        self.control_volume.properties_out.initialize(
            state_args=state_args_outlet,
            solver=solver,
            optarg=optarg,
            outlvl=outlvl,
            hold_state=False)

        if degrees_of_freedom(self) == 0:
            with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
                res = solver.solve(self, tee=slc.tee)
            init_log.info("Initialization Complete, {}.".format(
                idaeslog.condition(res)))
        else:
            raise ConfigurationError(
                "State vars fixed but degrees of freedom "
                "for reboiler is not zero during "
                "initialization. Please ensure that the boilup_ratio "
                "or the outlet temperature is fixed.")

        self.control_volume.properties_in.\
            release_state(flags=flags, outlvl=outlvl)
Beispiel #5
0
    def initialize(self,
                   state_args_feed=None,
                   state_args_liq=None,
                   state_args_vap=None,
                   hold_state_liq=False,
                   hold_state_vap=False,
                   solver=None,
                   optarg=None,
                   outlvl=idaeslog.NOTSET):

        # TODO:
        # 1. Initialization for dynamic mode. Currently not supported.
        # 2. Handle unfixed side split fraction vars
        # 3. Better logic to handle and fix state vars.

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

        init_log.info("Begin initialization.")

        if solver is None:
            init_log.warning("Solver not provided. Default solver(ipopt) "
                             " being used for initialization.")
            solver = get_default_solver()

        if self.config.has_liquid_side_draw:
            if not self.liq_side_sf.fixed:
                raise ConfigurationError(
                    "Liquid side draw split fraction not fixed but "
                    "has_liquid_side_draw set to True.")

        if self.config.has_vapor_side_draw:
            if not self.vap_side_sf.fixed:
                raise ConfigurationError(
                    "Vapor side draw split fraction not fixed but "
                    "has_vapor_side_draw set to True.")

        # Create initial guess if not provided by using current values
        if self.config.is_feed_tray and state_args_feed is None:
            state_args_feed = {}
            state_args_liq = {}
            state_args_vap = {}
            state_dict = (self.properties_in_feed[
                self.flowsheet().config.time.first()].define_port_members())

            for k in state_dict.keys():
                if "flow" in k:
                    if state_dict[k].is_indexed():
                        state_args_feed[k] = {}
                        state_args_liq[k] = {}
                        state_args_vap[k] = {}
                        for m in state_dict[k].keys():
                            state_args_feed[k][m] = \
                                value(state_dict[k][m])
                            state_args_liq[k][m] = \
                                value(0.1 * state_dict[k][m])
                            state_args_vap[k][m] = \
                                value(0.1 * state_dict[k][m])

                    else:
                        state_args_feed[k] = value(state_dict[k])
                        state_args_liq[k] = 0.1 * value(state_dict[k])
                        state_args_vap[k] = 0.1 * value(state_dict[k])
                else:
                    if state_dict[k].is_indexed():
                        state_args_feed[k] = {}
                        state_args_liq[k] = {}
                        state_args_vap[k] = {}
                        for m in state_dict[k].keys():
                            state_args_feed[k][m] = \
                                value(state_dict[k][m])
                            state_args_liq[k][m] = \
                                value(state_dict[k][m])
                            state_args_vap[k][m] = \
                                value(state_dict[k][m])

                    else:
                        state_args_feed[k] = value(state_dict[k])
                        state_args_liq[k] = value(state_dict[k])
                        state_args_vap[k] = value(state_dict[k])

        # Create initial guess if not provided by using current values
        if not self.config.is_feed_tray and state_args_liq is None:
            state_args_liq = {}
            state_dict = (self.properties_in_liq[
                self.flowsheet().config.time.first()].define_port_members())

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

        # Create initial guess if not provided by using current values
        if not self.config.is_feed_tray and state_args_vap is None:
            state_args_vap = {}
            state_dict = (self.properties_in_vap[
                self.flowsheet().config.time.first()].define_port_members())

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

        if self.config.is_feed_tray:
            feed_flags = self.properties_in_feed.initialize(
                outlvl=outlvl,
                solver=solver,
                optarg=optarg,
                hold_state=True,
                state_args=state_args_feed,
                state_vars_fixed=False)

        liq_in_flags = self.properties_in_liq. \
            initialize(outlvl=outlvl,
                       solver=solver,
                       optarg=optarg,
                       hold_state=True,
                       state_args=state_args_liq,
                       state_vars_fixed=False)

        vap_in_flags = self.properties_in_vap. \
            initialize(outlvl=outlvl,
                       solver=solver,
                       optarg=optarg,
                       hold_state=True,
                       state_args=state_args_vap,
                       state_vars_fixed=False)

        # state args to initialize the mixed outlet state block
        state_args_mixed = {}

        if self.config.is_feed_tray:

            # if feed tray, initialize the mixed state block at
            # the same condition.
            state_args_mixed = state_args_feed
        else:
            # if not feed tray, initialize mixed state block at average of
            # vap/liq inlets except pressure. While this is crude, it
            # will work for most combination of state vars.
            state_dict = (self.properties_in_liq[
                self.flowsheet().config.time.first()].define_port_members())
            for k in state_dict.keys():
                if k == "pressure":
                    # Take the lowest pressure and this is the liq inlet
                    state_args_mixed[k] = value(
                        self.properties_in_liq[0].component(
                            state_dict[k].local_name))
                elif state_dict[k].is_indexed():
                    state_args_mixed[k] = {}
                    for m in state_dict[k].keys():
                        if "flow" in k:
                            state_args_mixed[k][m] = \
                                value(self.properties_in_liq[0].
                                      component(state_dict[k].local_name)[m]) \
                                + value(self.properties_in_vap[0].
                                        component(state_dict[k].local_name)[m])

                        else:
                            state_args_mixed[k][m] = \
                                0.5 * (value(self.properties_in_liq[0].
                                             component(state_dict[k].
                                                       local_name)[m]) +
                                       value(self.properties_in_vap[0].
                                       component(state_dict[k].local_name)[m]))

                else:
                    if "flow" in k:
                        state_args_mixed[k] = \
                            value(self.properties_in_liq[0].
                                  component(state_dict[k].local_name)) +\
                            value(self.properties_in_vap[0].
                                  component(state_dict[k].local_name))
                    else:
                        state_args_mixed[k] = \
                            0.5 * (value(self.properties_in_liq[0].
                                         component(state_dict[k].local_name)) +
                                   value(self.properties_in_vap[0].
                                         component(state_dict[k].local_name)))

        # Initialize the mixed outlet state block
        self.properties_out. \
            initialize(outlvl=outlvl,
                       solver=solver,
                       optarg=optarg,
                       hold_state=False,
                       state_args=state_args_mixed,
                       state_vars_fixed=False)

        # Deactivate energy balance
        self.enthalpy_mixing_equations.deactivate()

        # Try fixing the outlet temperature if else pass
        # NOTE: if passed then there would probably be a degree of freedom
        try:
            self.properties_out[:].temperature.\
                fix(state_args_mixed["temperature"])
        except AttributeError:
            init_log.warning("Trying to fix outlet temperature "
                             "during initialization but temperature attribute "
                             "unavailable in the state block. Initialization "
                             "proceeding with a potential degree of freedom.")

        # Deactivate pressure balance
        self.pressure_drop_equation.deactivate()

        # Try fixing the outlet temperature if else pass
        # NOTE: if passed then there would probably be a degree of freedom
        try:
            self.properties_out[:].pressure.\
                fix(state_args_mixed["pressure"])
        except AttributeError:
            init_log.warning("Trying to fix outlet pressure "
                             "during initialization but pressure attribute "
                             "unavailable in the state block. Initialization "
                             "proceeding with a potential degree of freedom.")

        with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
            res = solver.solve(self, tee=slc.tee)
        init_log.info("Mass balance solve {}.".format(idaeslog.condition(res)))

        # Activate energy balance
        self.enthalpy_mixing_equations.activate()
        try:
            self.properties_out[:].temperature.unfix()
        except AttributeError:
            pass

        with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
            res = solver.solve(self, tee=slc.tee)
        init_log.info("Mass and energy balance solve {}.".format(
            idaeslog.condition(res)))

        # Activate pressure balance
        self.pressure_drop_equation.activate()
        try:
            self.properties_out[:].pressure.unfix()
        except AttributeError:
            pass

        if degrees_of_freedom(self) == 0:
            with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
                res = solver.solve(self, tee=slc.tee)
            init_log.info("Mass, energy and pressure balance solve {}.".format(
                idaeslog.condition(res)))
        else:
            raise Exception("State vars fixed but degrees of freedom "
                            "for tray block is not zero during "
                            "initialization.")

        init_log.info("Initialization complete, status {}.".format(
            idaeslog.condition(res)))

        if not self.config.is_feed_tray:
            if not hold_state_vap:
                self.properties_in_vap.release_state(flags=vap_in_flags,
                                                     outlvl=outlvl)
            if not hold_state_liq:
                self.properties_in_liq.release_state(flags=liq_in_flags,
                                                     outlvl=outlvl)
            if hold_state_liq and hold_state_vap:
                return liq_in_flags, vap_in_flags
            elif hold_state_vap:
                return vap_in_flags
            elif hold_state_liq:
                return liq_in_flags
        else:
            self.properties_in_liq.release_state(flags=liq_in_flags,
                                                 outlvl=outlvl)
            self.properties_in_vap.release_state(flags=vap_in_flags,
                                                 outlvl=outlvl)
            return feed_flags
Beispiel #6
0
    def initialize(blk,
                   state_args=None,
                   outlvl=idaeslog.NOTSET,
                   solver=None,
                   optarg={}):
        '''
        This is a general purpose initialization routine for simple unit
        models. This method assumes a single ControlVolume block called
        controlVolume, and first initializes this and then attempts to solve
        the entire unit.

        More complex models should overload this method with their own
        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={})
            solver : str indicating which solver to use during
                     initialization (default = None, use default IDAES solver)

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

        if solver is None:
            opt = get_default_solver()
        else:
            opt = SolverFactory(solver)
            opt.options = optarg

        # ---------------------------------------------------------------------
        # Initialize control volume block
        flags = blk.control_volume.initialize(
            outlvl=outlvl,
            optarg=optarg,
            solver=solver,
            state_args=state_args,
        )

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

        # ---------------------------------------------------------------------
        # Solve unit

        # if costing block exists, deactivate
        if hasattr(blk, "costing"):
            blk.costing.deactivate()

        with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
            results = opt.solve(blk, tee=slc.tee)

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

        # if costing block exists, activate and initialize
        if hasattr(blk, "costing"):
            blk.costing.activate()
            idaes.core.util.unit_costing.initialize(blk.costing)
        # ---------------------------------------------------------------------
        # Release Inlet state
        blk.control_volume.release_state(flags, outlvl)

        init_log.info('Initialization Complete: {}'.format(
            idaeslog.condition(results)))
    def initialize(self,
                   state_args_feed=None,
                   state_args_liq=None,
                   state_args_vap=None,
                   solver=None,
                   outlvl=idaeslog.NOTSET):

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

        init_log.info("Begin initialization.")

        if solver is None:
            init_log.warning("Solver not provided. Default solver(ipopt) "
                             "being used for initialization.")
            solver = get_default_solver()

        feed_flags = self.feed_tray.initialize()

        self.propagate_stream_state(source=self.feed_tray.vap_out,
                                    destination=self.condenser.inlet)

        self.condenser.initialize()

        self.propagate_stream_state(source=self.feed_tray.liq_out,
                                    destination=self.reboiler.inlet)

        self.reboiler.initialize()

        # initialize the rectification section
        for i in self._rectification_index:
            self.propagate_stream_state(
                source=self.condenser.reflux,
                destination=self.rectification_section[i].liq_in)
            self.propagate_stream_state(
                source=self.feed_tray.vap_out,
                destination=self.rectification_section[i].vap_in)
            if i == 1:
                rect_liq_flags = self.rectification_section[i]. \
                    initialize(hold_state_liq=True, hold_state_vap=False)
            elif i == len(self._rectification_index):
                rect_vap_flags = \
                    self.rectification_section[i]. \
                    initialize(hold_state_liq=False, hold_state_vap=True)
            else:
                self.rectification_section[i].initialize()

        # initialize the stripping section
        for i in self._stripping_index:
            self.propagate_stream_state(
                source=self.feed_tray.liq_out,
                destination=self.stripping_section[i].liq_in)
            self.propagate_stream_state(
                source=self.reboiler.vapor_reboil,
                destination=self.stripping_section[i].vap_in)
            if i == self.config.feed_tray_location + 1:
                strip_liq_flags = self.stripping_section[i]. \
                    initialize(hold_state_liq=True, hold_state_vap=False)
            elif i == self.config.number_of_trays:
                strip_vap_flags = self.stripping_section[i]. \
                    initialize(hold_state_liq=False, hold_state_vap=True)
            else:
                self.stripping_section[i].initialize()

        # For initialization purposes and to enable solving individual sections
        # creating a temp block. Note that this temp block is a reference to
        # the rectification, stripping, and feed sections. Also, expanded arcs
        # are added to the temp block as the initialization solve proceeds.
        self._temp_block = Block()

        self._temp_block.rectification = Block()

        # adding reference to the rectification section and the expanded
        # vapor and liquid arcs
        self._temp_block.rectification.trays = Reference(
            self.rectification_section)
        self._temp_block.rectification.expanded_liq_stream = Reference(
            self.rectification_liq_stream[:].expanded_block)
        self._temp_block.rectification.expanded_vap_stream = Reference(
            self.rectification_vap_stream[:].expanded_block)

        with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
            res = solver.solve(self._temp_block.rectification, tee=slc.tee)
        init_log.info("Rectification section initialization status {}.".format(
            idaeslog.condition(res)))

        self._temp_block.stripping = Block()

        # adding reference to the stripping section and the expanded
        # vapor and liquid arcs
        self._temp_block.stripping.trays = Reference(self.stripping_section)
        self._temp_block.stripping.expanded_liq_stream = Reference(
            self.stripping_liq_stream[:].expanded_block)
        self._temp_block.stripping.expanded_vap_stream = Reference(
            self.stripping_vap_stream[:].expanded_block)

        with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
            res = solver.solve(self._temp_block.stripping, tee=slc.tee)
        init_log.info("Stripping section initialization status {}.".format(
            idaeslog.condition(res)))

        # releasing the fixed inlets for the vap in to the rectification
        # to enable connection with the feed tray vap out
        self.rectification_section[len(self._rectification_index)]. \
            properties_in_vap. \
            release_state(flags=rect_vap_flags, outlvl=outlvl)

        # releasing the fixed inlets for the liq in to the stripping
        # to enable connection with the feed tray liq out
        self.stripping_section[self.config.feed_tray_location + 1]. \
            properties_in_liq. \
            release_state(flags=strip_liq_flags, outlvl=outlvl)

        # Adding the feed tray to temp block solve
        self._temp_block.feed_tray = Reference(self.feed_tray)
        self._temp_block.expanded_feed_liq_stream_in = Reference(
            self.feed_liq_in.expanded_block)
        self._temp_block.expanded_feed_liq_stream_out = Reference(
            self.feed_liq_out.expanded_block)
        self._temp_block.expanded_feed_vap_stream_in = Reference(
            self.feed_vap_in.expanded_block)
        self._temp_block.expanded_feed_vap_stream_out = Reference(
            self.feed_vap_out.expanded_block)

        with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
            res = solver.solve(self._temp_block, tee=slc.tee)
        init_log.info("Column section initialization status {}.".format(
            idaeslog.condition(res)))

        self.rectification_section[1]. \
            properties_in_liq. \
            release_state(flags=rect_liq_flags, outlvl=outlvl)

        # Adding the condenser to the temp block solve
        self._temp_block.condenser = Reference(self.condenser)
        self._temp_block.expanded_condenser_vap_in = Reference(
            self.condenser_vap_in.expanded_block)
        self._temp_block.expanded_condenser_reflux_out = Reference(
            self.condenser_reflux_out.expanded_block)

        with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
            res = solver.solve(self._temp_block, tee=slc.tee)
        init_log.info(
            "Column section + Condenser initialization status {}.".format(
                idaeslog.condition(res)))

        self.stripping_section[self.config.number_of_trays]. \
            properties_in_vap. \
            release_state(flags=strip_vap_flags, outlvl=outlvl)

        # Delete the _temp_block as next solve is solving the entire column.
        # If we add the reboiler to the temp block, it will be similar to
        # solving the original block. This ensures that if
        # initialize is triggered twice, there is no implicit replacing
        # component error.
        self.del_component(self._temp_block)

        with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
            res = solver.solve(self, tee=slc.tee)
        init_log.info(
            "Column section + Condenser + Reboiler initialization status {}.".
            format(idaeslog.condition(res)))

        # release feed tray state once initialization is complete
        self.feed_tray.properties_in_feed.\
            release_state(flags=feed_flags, outlvl=outlvl)