Example #1
0
def test_costing_FH_solve():
    m = pyo.ConcreteModel()
    m.fs = FlowsheetBlock(default={"dynamic": False})
    m.fs.get_costing()
    m.fs.costing.CE_index = 550  # for testing only
    m.fs.unit = pyo.Block()
    m.fs.unit.heat_duty = pyo.Var(initialize=1e6,
                                  units=pyo.units.BTU / pyo.units.hr)
    m.fs.unit.pressure = pyo.Var(initialize=1e5, units=pyo.units.psi)
    m.fs.unit.costing = pyo.Block()
    m.fs.unit.heat_duty.fix(18390000)  # Btu/hr
    m.fs.unit.pressure.fix(700)  # psig

    cs.fired_heater_costing(m.fs.unit.costing,
                            fired_type='fuel',
                            Mat_factor='stain_steel',
                            ref_parameter_pressure=m.fs.unit.pressure,
                            ref_parameter_heat_duty=m.fs.unit.heat_duty)

    assert degrees_of_freedom(m) == 0
    # Check unit config arguments
    assert isinstance(m.fs.unit.costing.purchase_cost, pyo.Var)
    assert isinstance(m.fs.unit.costing.base_cost_per_unit, pyo.Var)
    # initialize costing block
    costing.initialize(m.fs.unit.costing)
    assert (pytest.approx(pyo.value(m.fs.unit.costing.purchase_cost),
                          abs=1e-2) == 962795.521)
    results = solver.solve(m, tee=False)
    # Check for optimal solution
    assert results.solver.termination_condition == \
        pyo.TerminationCondition.optimal
    assert results.solver.status == pyo.SolverStatus.ok
    assert (pytest.approx(pyo.value(m.fs.unit.costing.purchase_cost),
                          abs=1e-2) == 962795.521)  # Example 22.1 Ref Book
Example #2
0
    def initialize(
        blk,
        state_args=None,
        routine=None,
        outlvl=idaeslog.NOTSET,
        solver="ipopt",
        optarg={"tol": 1e-6},
    ):
        """
        General wrapper for pressure changer initialization routines

        Keyword Arguments:
            routine : str stating which initialization routine to execute
                        * None - use routine matching thermodynamic_assumption
                        * 'isentropic' - use isentropic initialization routine
                        * 'isothermal' - use isothermal initialization routine
            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={'tol': 1e-6})
            solver : str indicating whcih solver to use during
                     initialization (default = 'ipopt')

        Returns:
            None
        """
        # if costing block exists, deactivate
        try:
            blk.costing.deactivate()
        except AttributeError:
            pass

        if routine is None:
            # Use routine for specific type of unit
            routine = blk.config.thermodynamic_assumption

        # Call initialization routine
        if routine is ThermodynamicAssumption.isentropic:
            blk.init_isentropic(state_args=state_args,
                                outlvl=outlvl,
                                solver=solver,
                                optarg=optarg)
        else:
            # Call the general initialization routine in UnitModelBlockData
            super(PressureChangerData, blk).initialize(state_args=state_args,
                                                       outlvl=outlvl,
                                                       solver=solver,
                                                       optarg=optarg)
        # if costing block exists, activate
        try:
            blk.costing.activate()
            costing.initialize(blk.costing)
        except AttributeError:
            pass
    def initialize(
        self,
        state_args_1=None,
        state_args_2=None,
        outlvl=idaeslog.NOTSET,
        solver="ipopt",
        optarg={"tol": 1e-6},
        duty=None,
    ):
        """
        Heat exchanger initialization method.

        Args:
            state_args_1 : a dict of arguments to be passed to the property
                initialization for the hot side (see documentation of the specific
                property package) (default = {}).
            state_args_2 : a dict of arguments to be passed to the property
                initialization for the cold side (see documentation of the specific
                property package) (default = {}).
            outlvl : sets output level of initialization routine
            optarg : solver options dictionary object (default={'tol': 1e-6})
            solver : str indicating which solver to use during
                     initialization (default = 'ipopt')
            duty : an initial guess for the amount of heat transfered. This
                should be a tuple in the form (value, units), (default
                = (1000 J/s))

        Returns:
            None

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

        hot_side = getattr(self, self.config.hot_side_name)
        cold_side = getattr(self, self.config.cold_side_name)

        opt = SolverFactory(solver)
        opt.options = optarg
        flags1 = hot_side.initialize(outlvl=outlvl,
                                     optarg=optarg,
                                     solver=solver,
                                     state_args=state_args_1)

        init_log.info_high("Initialization Step 1a (hot side) Complete.")

        flags2 = cold_side.initialize(outlvl=outlvl,
                                      optarg=optarg,
                                      solver=solver,
                                      state_args=state_args_2)

        init_log.info_high("Initialization Step 1b (cold side) Complete.")
        # ---------------------------------------------------------------------
        # Solve unit without heat transfer equation
        # if costing block exists, deactivate
        if hasattr(self, "costing"):
            self.costing.deactivate()

        self.heat_transfer_equation.deactivate()

        # Get side 1 and side 2 heat units, and convert duty as needed
        s1_units = hot_side.heat.get_units()
        s2_units = cold_side.heat.get_units()

        if duty is None:
            # Assume 1000 J/s and check for unitless properties
            if s1_units is None and s2_units is None:
                # Backwards compatability for unitless properties
                s1_duty = -1000
                s2_duty = 1000
            else:
                s1_duty = pyunits.convert_value(-1000,
                                                from_units=pyunits.W,
                                                to_units=s1_units)
                s2_duty = pyunits.convert_value(1000,
                                                from_units=pyunits.W,
                                                to_units=s2_units)
        else:
            # Duty provided with explicit units
            s1_duty = -pyunits.convert_value(
                duty[0], from_units=duty[1], to_units=s1_units)
            s2_duty = pyunits.convert_value(duty[0],
                                            from_units=duty[1],
                                            to_units=s2_units)

        cold_side.heat.fix(s2_duty)
        for i in hot_side.heat:
            hot_side.heat[i].value = s1_duty

        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)))
        cold_side.heat.unfix()
        self.heat_transfer_equation.activate()
        # ---------------------------------------------------------------------
        # Solve unit
        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)))
        # ---------------------------------------------------------------------
        # Release Inlet state
        hot_side.release_state(flags1, outlvl=outlvl)
        cold_side.release_state(flags2, outlvl=outlvl)

        init_log.info("Initialization Completed, {}".format(
            idaeslog.condition(res)))
        # if costing block exists, activate and initialize
        if hasattr(self, "costing"):
            self.costing.activate()
            costing.initialize(self.costing)
    def initialize(
        self,
        hot_side_state_args=None,
        cold_side_state_args=None,
        outlvl=idaeslog.NOTSET,
        solver=None,
        optarg=None,
        duty=None,
    ):
        """
        Heat exchanger initialization method.

        Args:
            hot_side_state_args : a dict of arguments to be passed to the
                property initialization for the hot side (see documentation of
                the specific property package) (default = None).
            cold_side_state_args : a dict of arguments to be passed to the
                property initialization for the cold side (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 solver)
            duty : an initial guess for the amount of heat transfered. This
                should be a tuple in the form (value, units), (default
                = (1000 J/s))

        Returns:
            None

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

        hot_side = self.hot_side
        cold_side = self.cold_side

        # Create solver
        opt = get_solver(solver, optarg)

        flags1 = hot_side.initialize(outlvl=outlvl,
                                     optarg=optarg,
                                     solver=solver,
                                     state_args=hot_side_state_args)

        init_log.info_high("Initialization Step 1a (hot side) Complete.")

        flags2 = cold_side.initialize(outlvl=outlvl,
                                      optarg=optarg,
                                      solver=solver,
                                      state_args=cold_side_state_args)

        init_log.info_high("Initialization Step 1b (cold side) Complete.")

        # ---------------------------------------------------------------------
        # Solve unit without heat transfer equation
        # if costing block exists, deactivate
        if hasattr(self, "costing"):
            self.costing.deactivate()

        self.energy_balance_constraint.deactivate()
        self.effectiveness_correlation.deactivate()
        self.effectiveness.fix(0.68)

        # Get side 1 and side 2 heat units, and convert duty as needed
        s1_units = hot_side.heat.get_units()
        s2_units = cold_side.heat.get_units()

        if duty is None:
            # Assume 1000 J/s and check for unitless properties
            if s1_units is None and s2_units is None:
                # Backwards compatability for unitless properties
                s1_duty = -1000
                s2_duty = 1000
            else:
                s1_duty = pyunits.convert_value(-1000,
                                                from_units=pyunits.W,
                                                to_units=s1_units)
                s2_duty = pyunits.convert_value(1000,
                                                from_units=pyunits.W,
                                                to_units=s2_units)
        else:
            # Duty provided with explicit units
            s1_duty = -pyunits.convert_value(
                duty[0], from_units=duty[1], to_units=s1_units)
            s2_duty = pyunits.convert_value(duty[0],
                                            from_units=duty[1],
                                            to_units=s2_units)

        cold_side.heat.fix(s2_duty)
        for i in hot_side.heat:
            hot_side.heat[i].value = s1_duty

        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)))

        cold_side.heat.unfix()
        self.energy_balance_constraint.activate()

        for t in self.effectiveness:
            calculate_variable_from_constraint(
                self.effectiveness[t], self.effectiveness_correlation[t])

        # ---------------------------------------------------------------------
        # Solve unit with new effectiveness factor
        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.effectiveness_correlation.activate()
        self.effectiveness.unfix()

        # ---------------------------------------------------------------------
        # Final solve of full modelr
        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)))

        # ---------------------------------------------------------------------
        # Release Inlet state
        hot_side.release_state(flags1, outlvl=outlvl)
        cold_side.release_state(flags2, outlvl=outlvl)

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

        # if costing block exists, activate and initialize
        if hasattr(self, "costing"):
            self.costing.activate()
            costing.initialize(self.costing)