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