def main(): # set up solver solver_dict = { 'solver_str': 'ipopt', 'solver_opt': { 'nlp_scaling_method': 'user-scaling' } } solver_dict['solver'] = SolverFactory(solver_dict['solver_str']) solver_dict['solver'].options = solver_dict['solver_opt'] # build, set, and initialize m = build() set_operating_conditions(m, solver=solver_dict['solver']) initialize_system(m, solver_dict=solver_dict) # simulate and display solve(m, solver=solver_dict['solver']) print('\n***---Simulation results---***') display_system(m) display_design(m) display_state(m) # optimize and display optimize(m, solver=solver_dict['solver']) print('\n***---Optimization results---***') display_system(m) display_design(m) display_state(m)
def unit_frame(self): m = ConcreteModel() m.fs = FlowsheetBlock(default={'dynamic': False}) m.fs.properties = props.SeawaterParameterBlock() m.fs.unit = PressureExchanger( default={'property_package': m.fs.properties}) # Specify inlet conditions temperature = 25 + 273.15 flow_vol = 1e-3 lowP_mass_frac_TDS = 0.035 lowP_pressure = 101325 highP_mass_frac_TDS = 0.07 highP_pressure = 50e5 m.fs.unit.low_pressure_side.properties_in[0].flow_vol_phase['Liq'].fix( flow_vol) m.fs.unit.low_pressure_side.properties_in[0].mass_frac_phase_comp[ 'Liq', 'TDS'].fix(lowP_mass_frac_TDS) m.fs.unit.low_pressure_side.properties_in[0].pressure.fix( lowP_pressure) m.fs.unit.low_pressure_side.properties_in[0].temperature.fix( temperature) m.fs.unit.high_pressure_side.properties_in[0].flow_vol_phase[ 'Liq'].fix(flow_vol) m.fs.unit.high_pressure_side.properties_in[0].mass_frac_phase_comp[ 'Liq', 'TDS'].fix(highP_mass_frac_TDS) m.fs.unit.high_pressure_side.properties_in[0].pressure.fix( highP_pressure) m.fs.unit.high_pressure_side.properties_in[0].temperature.fix( temperature) # solve inlet conditions and only fix state variables (i.e. unfix flow_vol and mass_frac_phase) solver = SolverFactory('ipopt') solver.options = {'nlp_scaling_method': 'user-scaling'} results = solver.solve(m.fs.unit.low_pressure_side.properties_in[0]) assert results.solver.termination_condition == TerminationCondition.optimal m.fs.unit.low_pressure_side.properties_in[0].flow_mass_phase_comp[ 'Liq', 'TDS'].fix() m.fs.unit.low_pressure_side.properties_in[0].flow_vol_phase[ 'Liq'].unfix() m.fs.unit.low_pressure_side.properties_in[0].mass_frac_phase_comp[ 'Liq', 'TDS'].unfix() results = solver.solve(m.fs.unit.high_pressure_side.properties_in[0]) assert results.solver.termination_condition == TerminationCondition.optimal m.fs.unit.high_pressure_side.properties_in[0].flow_mass_phase_comp[ 'Liq', 'H2O'].fix() m.fs.unit.high_pressure_side.properties_in[0].flow_mass_phase_comp[ 'Liq', 'TDS'].fix() m.fs.unit.high_pressure_side.properties_in[0].flow_vol_phase[ 'Liq'].unfix() m.fs.unit.high_pressure_side.properties_in[0].mass_frac_phase_comp[ 'Liq', 'TDS'].unfix() # Specify unit efficiency = 0.95 m.fs.unit.efficiency_pressure_exchanger.fix(efficiency) return m
def initialize(blk, state_args=None, outlvl=idaeslog.NOTSET, solver='ipopt', optarg={'tol': 1e-6}): ''' 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={'tol': 1e-6}) solver : str indicating which solver to use during initialization (default = 'ipopt') Returns: None ''' # Set solver options init_log = idaeslog.getInitLogger(blk.name, outlvl, tag="unit") solve_log = idaeslog.getSolveLogger(blk.name, outlvl, tag="unit") 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 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))) # --------------------------------------------------------------------- # Release Inlet state blk.control_volume.release_state(flags, outlvl + 1) init_log.info('Initialization Complete: {}'.format( idaeslog.condition(results)))
def initialize(blk, state_args=None, outlvl=0, solver='ipopt', optarg={'tol': 1e-6}): ''' Downcomer initialization routine. Keyword Arguments: state_args : a dict of arguments to be passed to the property package(s) for the control_volume of the model to provide an initial state for initialization (see documentation of the specific property package) (default = None). outlvl : sets output level of initialisation routine optarg : solver options dictionary object (default={'tol': 1e-6}) solver : str indicating whcih solver to use during initialization (default = 'ipopt') Returns: None ''' init_log = idaeslog.getInitLogger(blk.name, outlvl, tag="unit") solve_log = idaeslog.getSolveLogger(blk.name, outlvl, tag="unit") opt = SolverFactory(solver) opt.options = optarg flags = blk.control_volume.initialize( outlvl=outlvl + 1, optarg=optarg, solver=solver, state_args=state_args, ) init_log.info_high("Initialization Step 1 Complete.") # Fix outlet enthalpy and pressure for t in blk.flowsheet().config.time: blk.control_volume.properties_out[t].pressure.fix( value(blk.control_volume.properties_in[t].pressure)) blk.pressure_change_total_eqn.deactivate() with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: res = opt.solve(blk, tee=slc.tee) init_log.info_high("Initialization Step 2 {}.".format( idaeslog.condition(res))) # Unfix outlet enthalpy and pressure for t in blk.flowsheet().config.time: blk.control_volume.properties_out[t].pressure.unfix() blk.pressure_change_total_eqn.activate() 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))) blk.control_volume.release_state(flags, outlvl + 1) init_log.info("Initialization Complete.")
def initialize(blk, state_args_water_steam={}, outlvl=0, solver='ipopt', optarg={'tol': 1e-6}): ''' Drum initialization routine. Keyword Arguments: state_args : a dict of arguments to be passed to the property package(s) for the control_volume of the model to provide an initial state for initialization (see documentation of the specific property package) (default = None). outlvl : sets output level of initialisation routine * 0 = no output (default) * 1 = return solver state for each step in routine * 2 = return solver state for each step in subroutines * 3 = include solver output infomation (tee=True) optarg : solver options dictionary object (default={'tol': 1e-6}) solver : str indicating whcih solver to use during initialization (default = 'ipopt') Returns: None ''' init_log = idaeslog.getInitLogger(blk.name, outlvl, tag="unit") solve_log = idaeslog.getSolveLogger(blk.name, outlvl, tag="unit") opt = SolverFactory(solver) opt.options = optarg init_log.info_low("Starting initialization...") # fix FeedWater Inlet flags_fw = fix_state_vars(blk.mixed_state, state_args_water_steam) blk.mixed_state.initialize() # initialize outlet states for t in blk.flowsheet().config.time: blk.vap_state[t].flow_mol = value(blk.mixed_state[t].flow_mol * blk.mixed_state[t].vapor_frac) blk.vap_state[t].enth_mol = value( blk.mixed_state[t].enth_mol_phase["Vap"]) blk.vap_state[t].pressure = value(blk.mixed_state[t].pressure) blk.vap_state[t].vapor_frac = 1 blk.liq_state[t].flow_mol = value( blk.mixed_state[t].flow_mol * (1 - blk.mixed_state[t].vapor_frac)) blk.liq_state[t].enth_mol = value( blk.mixed_state[t].enth_mol_phase["Liq"]) blk.liq_state[t].pressure = value(blk.mixed_state[t].pressure) blk.liq_state[t].vapor_frac = 0 # unfix variables revert_state_vars(blk.mixed_state, flags_fw) init_log.info_low("Initialization Complete.")
def initialize(self, outlvl=idaeslog.NOTSET, optarg={}, solver="ipopt"): """ Initialization routine for mixer (default solver ipopt) Keyword Arguments: outlvl : sets output level of initialization routine optarg : solver options dictionary object (default={}) solver : str indicating whcih solver to use during initialization (default = 'ipopt') Returns: None """ init_log = idaeslog.getInitLogger(self.name, outlvl, tag="unit") solve_log = idaeslog.getSolveLogger(self.name, outlvl, tag="unit") # Set solver options opt = SolverFactory(solver) opt.options = optarg # This shouldn't require too much initializtion, just fixing inlets # and solving should always work. # sp is what to save to make sure state after init is same as the start sp = StoreSpec.value_isfixed_isactive(only_fixed=True) istate = to_json(self, return_dict=True, wts=sp) for b in self.inlet_blocks.values(): for bdat in b.values(): bdat.pressure.fix() bdat.enth_mol.fix() bdat.flow_mol.fix() for t, v in self.outlet.pressure.items(): if not v.fixed: v.value = min([ value(self.inlet_blocks[i][t].pressure) for i in self.inlet_blocks ]) self.outlet.unfix() if (hasattr(self, "pressure_equality_constraints") and self.pressure_equality_constraints.active): # If using the equal pressure constraint fix the outlet and free # the inlet pressures, this is typical for pressure driven flow for i, b in self.inlet_blocks.items(): for bdat in b.values(): bdat.pressure.unfix() self.outlet.pressure.fix() 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))) from_json(self, sd=istate, wts=sp)
def get_default_solver(): """ Tries to set-up the default solver for testing, and returns None if not available """ if SolverFactory('ipopt').available(exception_flag=False): solver = SolverFactory('ipopt') solver.options = {'tol': 1e-6} else: solver = None return solver
def initialize(self, *args, **kwargs): """ Use the regular heat exchanger initialization, with the extraction rate constraint deactivated; then it activates the constraint and calculates a steam inlet flow rate. """ solver = kwargs.get("solver", "ipopt") optarg = kwargs.get("oparg", {}) outlvl = kwargs.get("outlvl", idaeslog.NOTSET) init_log = idaeslog.getInitLogger(self.name, outlvl, tag="unit") solve_log = idaeslog.getSolveLogger(self.name, outlvl, tag="unit") sp = StoreSpec.value_isfixed_isactive(only_fixed=True) istate = to_json(self, return_dict=True, wts=sp) self.area.fix() self.overall_heat_transfer_coefficient.fix() self.inlet_1.fix() self.inlet_2.fix() self.outlet_1.unfix() self.outlet_2.unfix() # Do condenser initialization self.inlet_1.flow_mol.unfix() # fix volume and pressure drop since # the condenser initialization dosen't require them self.side_1.volume.fix(10) self.side_1.deltaP.fix(0) self.shell_volume_eqn.deactivate() self.pressure_change_total_eqn.deactivate() super().initialize() self.side_1.volume.unfix() self.side_1.deltaP.unfix() self.shell_volume_eqn.activate() self.pressure_change_total_eqn.activate() opt = SolverFactory(solver) opt.options = optarg with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: res = opt.solve(self, tee=slc.tee) init_log.info( "Initialization Complete (w/ steam flow calc): {}".format( idaeslog.condition(res) ) ) from_json(self, sd=istate, wts=sp)
def initialize(blk, state_args={}, outlvl=0, solver='ipopt', optarg={'tol': 1e-6}): ''' This method initializes the StateJunction block by calling the initialize method on the property block. 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 initialisation routine * 0 = no output (default) * 1 = return solver state for each step in routine * 2 = return solver state for each step in subroutines * 3 = include solver output infomation (tee=True) optarg : solver options dictionary object (default={'tol': 1e-6}) solver : str indicating which solver to use during initialization (default = 'ipopt') Returns: None ''' # Set solver options opt = SolverFactory(solver) opt.options = optarg # --------------------------------------------------------------------- # Initialize control volume block blk.properties.initialize(outlvl=outlvl - 1, optarg=optarg, solver=solver, hold_state=False, **state_args) if outlvl > 0: _log.info('{} Initialisation Step Complete.'.format(blk.name))
def initialize(self, *args, **kwargs): """ Use the regular heat exchanger initilization, with the extraction rate constraint deactivated; then it activates the constraint and calculates a steam inlet flow rate. """ self.extraction_rate_constraint.deactivate() super().initialize(*args, **kwargs) self.extraction_rate_constraint.activate() solver = kwargs.get("solver", "ipopt") optarg = kwargs.get("oparg", {}) outlvl = kwargs.get("outlvl", 0) opt = SolverFactory(solver) opt.options = optarg tee = True if outlvl >= 3 else False sp = StoreSpec.value_isfixed_isactive(only_fixed=True) istate = to_json(self, return_dict=True, wts=sp) self.area.fix() self.overall_heat_transfer_coefficient.fix() self.inlet_1.fix() self.inlet_2.fix() self.outlet_1.unfix() self.outlet_2.unfix() self.inlet_1.flow_mol.unfix() results = opt.solve(self, tee=tee) if results.solver.termination_condition == TerminationCondition.optimal: if outlvl >= 2: _log.info('{} Initialization Failed.'.format(self.name)) else: _log.warning('{} Initialization Failed.'.format(self.name)) from_json(self, sd=istate, wts=sp)
def initialize(blk, state_args_1=None, state_args_2=None, state_args_3=None, outlvl=idaeslog.NOTSET, solver='ipopt', optarg={'tol': 1e-6}): ''' General Heat Exchanger initialisation routine. Keyword Arguments: state_args_1 : a dict of arguments to be passed to the property package(s) for side 1 of the heat exchanger to provide an initial state for initialization (see documentation of the specific property package) (default = None). state_args_2 : a dict of arguments to be passed to the property package(s) for side 2 of the heat exchanger to provide an initial state for initialization (see documentation of the specific property package) (default = None). state_args_3 : a dict of arguments to be passed to the property package(s) for side 3 of the heat exchanger to provide an initial state for initialization (see documentation of the specific property package) (default = None). outlvl : sets output level of initialisation routine optarg : solver options dictionary object (default={'tol': 1e-6}) solver : str indicating whcih solver to use during initialization (default = 'ipopt') Returns: None ''' init_log = idaeslog.getInitLogger(blk.name, outlvl, tag="unit") solve_log = idaeslog.getSolveLogger(blk.name, outlvl, tag="unit") opt = SolverFactory(solver) opt.options = optarg # --------------------------------------------------------------------- # Initialize inlet property blocks flags1 = blk.side_1.initialize(outlvl=outlvl, optarg=optarg, solver=solver, state_args=state_args_1) flags2 = blk.side_2.initialize(outlvl=outlvl, optarg=optarg, solver=solver, state_args=state_args_2) flags3 = blk.side_3.initialize(outlvl=outlvl, optarg=optarg, solver=solver, state_args=state_args_3) init_log.info('Initialisation Step 1 Complete.') with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: res = opt.solve(blk, tee=slc.tee) init_log.info("Initialization Step 2 Complete: {}".format( idaeslog.condition(res))) # --------------------------------------------------------------------- # Release Inlet state blk.side_1.release_state(flags1, outlvl) blk.side_2.release_state(flags2, outlvl) blk.side_3.release_state(flags3, outlvl) init_log.info_low("Initialization Complete: {}".format( idaeslog.condition(res)))
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 # approaches which can be implimented if the need arises. # initialize desuperheat if include 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(*args, **kwargs) # 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) # Solve all together opt = SolverFactory(kwargs.get("solver", "ipopt")) opt.options = 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(self, *args, **kwargs): config = self.config # sorter 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 initilization 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 # approaches which can be implimented if the need arises. # initialize desuperheat if include 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() self.condense.initialize(*args, **kwargs) # 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) # Solve all together outlvl = kwargs.get("outlvl", 0) opt = SolverFactory(kwargs.get("solver", "ipopt")) opt.options = kwargs.get("oparg", {}) tee = True if outlvl >= 3 else False assert (degrees_of_freedom(self) == 0) results = opt.solve(self, tee=tee) if results.solver.termination_condition == TerminationCondition.optimal: if outlvl >= 2: _log.info('{} Initialization Complete.'.format(self.name)) else: _log.warning('{} Initialization Failed.'.format(self.name)) from_json(self, sd=istate, wts=sp)
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, state_args={}, outlvl=idaeslog.NOTSET, solver="ipopt", optarg={ "tol": 1e-6, "max_iter": 30 }, calculate_cf=True, ): """ Initialize the outlet turbine stage model. This deactivates the specialized constraints, then does the isentropic turbine initialization, then reactivates the constraints and solves. Args: state_args (dict): Initial state for property initialization outlvl : sets output level of initialization routine 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") sp = StoreSpec.value_isfixed_isactive(only_fixed=True) istate = to_json(self, return_dict=True, wts=sp) # sp is what to save to make sure state after init is same as the start # saves value, fixed, and active state, doesn't load originally free # values, this makes sure original problem spec is same but initializes # the values of free vars for t in self.flowsheet().config.time: if self.outlet.pressure[t].fixed: self.ratioP[t] = value(self.outlet.pressure[t] / self.inlet.pressure[t]) self.deltaP[t] = value(self.outlet.pressure[t] - self.inlet.pressure[t]) # Deactivate special constraints self.stodola_equation.deactivate() self.efficiency_correlation.deactivate() self.efficiency_isentropic.fix() self.deltaP.unfix() self.ratioP.unfix() self.inlet.fix() self.outlet.unfix() super().initialize(outlvl=outlvl, solver=solver, optarg=optarg) for t in self.flowsheet().config.time: mw = self.control_volume.properties_in[t].mw Tin = self.control_volume.properties_in[t].temperature Pin = self.control_volume.properties_in[t].pressure Pr = self.ratioP[t] if not calculate_cf: cf = self.flow_coeff self.inlet.flow_mol[t].fix( value(cf * Pin * sqrt(1 - Pr**2) / mw / sqrt(Tin))) super().initialize(outlvl=outlvl, solver=solver, optarg=optarg) self.control_volume.properties_out[:].pressure.fix() # Free eff_isen and activate sepcial constarints self.efficiency_isentropic.unfix() self.outlet.pressure.fix() if calculate_cf: self.flow_coeff.unfix() self.inlet.flow_mol.unfix() self.inlet.flow_mol[0].fix() flow = self.control_volume.properties_in[0].flow_mol mw = self.control_volume.properties_in[0].mw Tin = self.control_volume.properties_in[0].temperature Pin = self.control_volume.properties_in[0].pressure Pr = self.ratioP[0] self.flow_coeff.value = value(flow * mw * sqrt(Tin / (1 - Pr**2)) / Pin) else: self.inlet.flow_mol.unfix() self.stodola_equation.activate() self.efficiency_correlation.activate() slvr = SolverFactory(solver) slvr.options = optarg self.display() with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: res = slvr.solve(self, tee=slc.tee) init_log.info("Initialization Complete (Outlet Stage): {}".format( idaeslog.condition(res))) # reload original spec if calculate_cf: cf = value(self.flow_coeff) from_json(self, sd=istate, wts=sp) if calculate_cf: # cf was probably fixed, so will have to set the value agian here # if you ask for it to be calculated. self.flow_coeff = cf
import pytest from pyomo.environ import ConcreteModel, SolverFactory, TransformationFactory from idaes.core import FlowsheetBlock from idaes.unit_models.power_generation import SteamValve from idaes.property_models import iapws95 from idaes.core.util.model_statistics import (degrees_of_freedom, activated_equalities_generator) prop_available = iapws95.iapws95_available() # See if ipopt is available and set up solver if SolverFactory('ipopt').available(): solver = SolverFactory('ipopt') solver.options = {'tol': 1e-6} else: solver = None @pytest.fixture() def build_valve_vapor(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.properties = iapws95.Iapws95ParameterBlock() m.fs.valve = SteamValve(default={"property_package": m.fs.properties}) return m @pytest.fixture() def build_valve_liquid():
def initialize(self, state_args_1=None, state_args_2=None, outlvl=0, solver='ipopt', optarg={'tol': 1e-6}, duty=1000): """ Heat exchanger initialization method. Args: state_args_1 : a dict of arguments to be passed to the property initialization for shell (see documentation of the specific property package) (default = {}). state_args_2 : a dict of arguments to be passed to the property initialization for tube (see documentation of the specific property package) (default = {}). outlvl : sets output level of initialisation routine * 0 = no output (default) * 1 = return solver state for each step in routine * 2 = return solver state for each step in subroutines * 3 = include solver output infomation (tee=True) 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 (default = 10000) Returns: None """ # Set solver options tee = True if outlvl >= 3 else False opt = SolverFactory(solver) opt.options = optarg flags1 = self.shell.initialize(outlvl=outlvl - 1, optarg=optarg, solver=solver, state_args=state_args_1) if outlvl > 0: _log.info('{} Initialization Step 1a (shell) Complete.'.format( self.name)) flags2 = self.tube.initialize(outlvl=outlvl - 1, optarg=optarg, solver=solver, state_args=state_args_2) if outlvl > 0: _log.info('{} Initialization Step 1b (tube) Complete.'.format( self.name)) # --------------------------------------------------------------------- # Solve unit without heat transfer equation self.heat_transfer_equation.deactivate() self.tube.heat.fix(duty) results = opt.solve(self, tee=tee, symbolic_solver_labels=True) if outlvl > 0: if results.solver.termination_condition == \ TerminationCondition.optimal: _log.info('{} Initialization Step 2 Complete.'.format( self.name)) else: _log.warning('{} Initialization Step 2 Failed.'.format( self.name)) self.tube.heat.unfix() self.heat_transfer_equation.activate() # --------------------------------------------------------------------- # Solve unit results = opt.solve(self, tee=tee, symbolic_solver_labels=True) if outlvl > 0: if results.solver.termination_condition == \ TerminationCondition.optimal: _log.info('{} Initialization Step 3 Complete.'.format( self.name)) else: _log.warning('{} Initialization Step 3 Failed.'.format( self.name)) # --------------------------------------------------------------------- # Release Inlet state self.shell.release_state(flags1, outlvl - 1) self.tube.release_state(flags2, outlvl - 1) if outlvl > 0: _log.info('{} Initialization Complete.'.format(self.name))
def initialize(self, state_args={}, outlvl=0, solver='ipopt', optarg={'tol': 1e-6, 'max_iter':30}): """ Initialize the inlet turbine stage model. This deactivates the specialized constraints, then does the isentropic turbine initialization, then reactivates the constraints and solves. Args: state_args (dict): Initial state for property initialization outlvl (int): Amount of output (0 to 3) 0 is lowest solver (str): Solver to use for initialization optarg (dict): Solver arguments dictionary """ stee = True if outlvl >= 3 else False # sp is what to save to make sure state after init is same as the start # saves value, fixed, and active state, doesn't load originally free # values, this makes sure original problem spec is same but initializes # the values of free vars sp = StoreSpec.value_isfixed_isactive(only_fixed=True) istate = to_json(self, return_dict=True, wts=sp) # Deactivate special constraints self.inlet_flow_constraint.deactivate() self.isentropic_enthalpy.deactivate() self.efficiency_correlation.deactivate() self.deltaP.unfix() self.ratioP.unfix() # Fix turbine parameters + eff_isen self.eff_nozzle.fix() self.blade_reaction.fix() self.flow_coeff.fix() self.blade_velocity.fix() # fix inlet and free outlet for t in self.flowsheet().config.time: for k, v in self.inlet.vars.items(): v[t].fix() for k, v in self.outlet.vars.items(): v[t].unfix() # If there isn't a good guess for efficeny or outlet pressure # provide something reasonable. eff = self.efficiency_isentropic[t] eff.fix(eff.value if value(eff) > 0.3 and value(eff) < 1.0 else 0.8) # for outlet pressure try outlet pressure, pressure ratio, delta P, # then if none of those look reasonable use a pressure ratio of 0.8 # to calculate outlet pressure Pout = self.outlet.pressure[t] Pin = self.inlet.pressure[t] prdp = value((self.deltaP[t] - Pin)/Pin) if value(Pout/Pin) > 0.98 or value(Pout/Pin) < 0.3: if value(self.ratioP[t]) < 0.98 and value(self.ratioP[t]) > 0.3: Pout.fix(value(Pin*self.ratioP)) elif prdp < 0.98 and prdp > 0.3: Pout.fix(value(prdp*Pin)) else: Pout.fix(value(Pin*0.8)) else: Pout.fix() self.deltaP[:] = value(Pout - Pin) self.ratioP[:] = value(Pout/Pin) for t in self.flowsheet().config.time: self.properties_isentropic[t].pressure.value = \ value(self.outlet.pressure[t]) self.properties_isentropic[t].flow_mol.value = \ value(self.inlet.flow_mol[t]) self.properties_isentropic[t].enth_mol.value = \ value(self.inlet.enth_mol[t]*0.95) self.outlet.flow_mol[t].value = \ value(self.inlet.flow_mol[t]) self.outlet.enth_mol[t].value = \ value(self.inlet.enth_mol[t]*0.95) # Make sure the initialization problem has no degrees of freedom # This shouldn't happen here unless there is a bug in this dof = degrees_of_freedom(self) try: assert(dof == 0) except: _log.exception("degrees_of_freedom = {}".format(dof)) raise # one bad thing about reusing this is that the log messages aren't # really compatible with being nested inside another initialization super(TurbineInletStageData, self).initialize(state_args=state_args, outlvl=outlvl, solver=solver, optarg=optarg) # Free eff_isen and activate sepcial constarints self.efficiency_isentropic.unfix() self.outlet.pressure.unfix() self.inlet_flow_constraint.activate() self.isentropic_enthalpy.activate() self.efficiency_correlation.activate() slvr = SolverFactory(solver) slvr.options = optarg res = slvr.solve(self, tee=stee) if outlvl > 0: if res.solver.termination_condition == TerminationCondition.optimal: _log.info("{} Initialization Complete.".format(self.name)) else: _log.warning( """{} Initialization Failed. The most likely cause of initialization failure for the Turbine inlet stages model is that the flow coefficient is not compatible with flow rate guess.""".format(self.name)) # reload original spec from_json(self, sd=istate, wts=sp)
def init_isentropic(blk, state_args, outlvl, solver, optarg): ''' Initialisation routine for 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 initialisation routine * 0 = no output (default) * 1 = return solver state for each step in routine * 2 = return solver state for each step in subroutines * 3 = include solver output infomation (tee=True) optarg : solver options dictionary object (default={'tol': 1e-6}) solver : str indicating whcih solver to use during initialization (default = 'ipopt') Returns: None ''' # Set solver options if outlvl > 3: stee = True else: stee = False opt = SolverFactory(solver) opt.options = optarg # --------------------------------------------------------------------- # Initialize Isentropic block blk.control_volume.properties_in.initialize(outlvl=outlvl-1, optarg=optarg, solver=solver, state_args=state_args) if outlvl > 0: logger.info('{} Initialisation Step 1 Complete.'.format(blk.name)) # --------------------------------------------------------------------- # Initialize holdup block flags = blk.control_volume.initialize(outlvl=outlvl-1, optarg=optarg, solver=solver, state_args=state_args) if outlvl > 0: logger.info('{} Initialisation Step 2 Complete.'.format(blk.name)) # --------------------------------------------------------------------- # Solve for isothermal conditions if isinstance( blk.control_volume.properties_in[ blk.flowsheet().config.time[1]].temperature, Var): for t in blk.flowsheet().config.time: blk.control_volume.properties_in[t].temperature.fix() blk.isentropic.deactivate() results = opt.solve(blk, tee=stee) if outlvl > 0: if results.solver.termination_condition == \ TerminationCondition.optimal: logger.info('{} Initialisation Step 3 Complete.' .format(blk.name)) else: logger.warning('{} Initialisation Step 3 Failed.' .format(blk.name)) for t in blk.flowsheet().config.time: blk.control_volume.properties_in[t].temperature.unfix() blk.isentropic.activate() elif outlvl > 0: logger.info('{} Initialisation Step 3 Skipped.'.format(blk.name)) # --------------------------------------------------------------------- # Solve unit results = opt.solve(blk, tee=stee) if outlvl > 0: if results.solver.termination_condition == \ TerminationCondition.optimal: logger.info('{} Initialisation Step 4 Complete.' .format(blk.name)) else: logger.warning('{} Initialisation Step 4 Failed.' .format(blk.name)) # --------------------------------------------------------------------- # Release Inlet state blk.control_volume.release_state(flags, outlvl-1) if outlvl > 0: logger.info('{} Initialisation Complete.'.format(blk.name))
def initialize( self, state_args={}, outlvl=idaeslog.NOTSET, solver="ipopt", optarg={"tol": 1e-6, "max_iter": 30}, calculate_cf=False, ): """ Initialize the inlet turbine stage model. This deactivates the specialized constraints, then does the isentropic turbine initialization, then reactivates the constraints and solves. This initializtion uses a flow value guess, so some reasonable flow guess should be sepecified prior to initializtion. Args: state_args (dict): Initial state for property initialization outlvl (int): Amount of output (0 to 3) 0 is lowest solver (str): Solver to use for initialization optarg (dict): Solver arguments dictionary calculate_cf (bool): If True, use the flow and pressure ratio to calculate the flow coefficient. """ init_log = idaeslog.getInitLogger(self.name, outlvl, tag="unit") solve_log = idaeslog.getSolveLogger(self.name, outlvl, tag="unit") # sp is what to save to make sure state after init is same as the start sp = StoreSpec.value_isfixed_isactive(only_fixed=True) istate = to_json(self, return_dict=True, wts=sp) # Setup for initializtion step 1 self.inlet_flow_constraint.deactivate() self.efficiency_correlation.deactivate() self.eff_nozzle.fix() self.blade_reaction.fix() self.flow_coeff.fix() self.blade_velocity.fix() self.inlet.fix() self.outlet.unfix() for t in self.flowsheet().config.time: self.efficiency_isentropic[t] = 0.9 super().initialize(outlvl=outlvl, solver=solver, optarg=optarg) # Free eff_isen and activate sepcial constarints self.inlet_flow_constraint.activate() self.efficiency_correlation.activate() if calculate_cf: self.ratioP.fix() self.flow_coeff.unfix() for t in self.flowsheet().config.time: g = self.control_volume.properties_in[t].heat_capacity_ratio mw = self.control_volume.properties_in[t].mw flow = self.control_volume.properties_in[t].flow_mol Tin = self.control_volume.properties_in[t].temperature Pin = self.control_volume.properties_in[t].pressure Pratio = self.ratioP[t] self.flow_coeff[t].value = value( flow * mw * sqrt( Tin/(g/(g - 1) *(Pratio**(2.0/g) - Pratio**((g + 1)/g))) )/Pin ) slvr = SolverFactory(solver) slvr.options = optarg with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: res = slvr.solve(self, tee=slc.tee) init_log.info("Initialization Complete: {}".format(idaeslog.condition(res))) # reload original spec if calculate_cf: cf = {} for t in self.flowsheet().config.time: cf[t] = value(self.flow_coeff[t]) from_json(self, sd=istate, wts=sp) if calculate_cf: # cf was probably fixed, so will have to set the value agian here # if you ask for it to be calculated. for t in self.flowsheet().config.time: self.flow_coeff[t] = cf[t]
def initialize( self, state_args_1=None, state_args_2=None, outlvl=idaeslog.NOTSET, solver="ipopt", optarg={"tol": 1e-6}, duty=1000, ): """ Heat exchanger initialization method. Args: state_args_1 : a dict of arguments to be passed to the property initialization for side_1 (see documentation of the specific property package) (default = {}). state_args_2 : a dict of arguments to be passed to the property initialization for side_2 (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 (default = 10000) Returns: None """ # Set solver options init_log = idaeslog.getInitLogger(self.name, outlvl, tag="unit") solve_log = idaeslog.getSolveLogger(self.name, outlvl, tag="unit") opt = SolverFactory(solver) opt.options = optarg flags1 = self.side_1.initialize(outlvl=outlvl, optarg=optarg, solver=solver, state_args=state_args_1) init_log.info_high("Initialization Step 1a (side_1) Complete.") flags2 = self.side_2.initialize(outlvl=outlvl, optarg=optarg, solver=solver, state_args=state_args_2) init_log.info_high("Initialization Step 1b (side_2) Complete.") # --------------------------------------------------------------------- # Solve unit without heat transfer equation self.heat_transfer_equation.deactivate() self.side_2.heat.fix(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))) self.side_2.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 self.side_1.release_state(flags1, outlvl=outlvl) self.side_2.release_state(flags2, outlvl=outlvl) init_log.info("Initialization Completed, {}".format( idaeslog.condition(res)))
def initialize(blk, outlvl=0, optarg={}, solver='ipopt', hold_state=False): ''' Initialisation routine for mixer (default solver ipopt) Keyword Arguments: outlvl : sets output level of initialisation routine. **Valid values:** **0** - no output (default), **1** - return solver state for each step in routine, **2** - include solver output infomation (tee=True) optarg : solver options dictionary object (default={}) 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. **Valid values:** **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. ''' # Set solver options if outlvl > 1: stee = True else: stee = False opt = SolverFactory(solver) opt.options = optarg # Initialize inlet state blocks flags = {} inlet_list = blk.create_inlet_list() i_block_list = [] for i in inlet_list: i_block = getattr(blk, i + "_state") i_block_list.append(i_block) flags[i] = {} flags[i] = i_block.initialize(outlvl=outlvl - 1, optarg=optarg, solver=solver, hold_state=True) # Initialize mixed state block if blk.config.mixed_state_block is None: mblock = blk.mixed_state else: mblock = blk.config.mixed_state_block # Calculate initial guesses for mixed stream state for t in blk.flowsheet().config.time: # Iterate over state vars as defined by property package s_vars = mblock[t].define_state_vars() for s in s_vars: i_vars = [] for i in range(len(i_block_list)): i_vars.append( getattr(i_block_list[i][t], s_vars[s].local_name)) if s == "pressure": # If pressure, use minimum as initial guess mblock[t].pressure.value = min( i_block_list[i][t].pressure.value for i in range(len(i_block_list))) elif "flow" in s: # If a "flow" variable (i.e. extensive), sum inlets for k in s_vars[s]: s_vars[s][k].value = sum( i_vars[i][k].value for i in range(len(i_block_list))) else: # Otherwise use average of inlets for k in s_vars[s]: s_vars[s][k].value = ( sum(i_vars[i][k].value for i in range(len(i_block_list))) / len(i_block_list)) mblock.initialize(outlvl=outlvl - 1, optarg=optarg, solver=solver, hold_state=False) if blk.config.mixed_state_block is None: if (hasattr(blk, "pressure_equality_constraints") and blk.pressure_equality_constraints.active is True): blk.pressure_equality_constraints.deactivate() for t in blk.flowsheet().config.time: sys_press = getattr(blk, blk.create_inlet_list()[0] + "_state")[t].pressure blk.mixed_state[t].pressure.fix(sys_press.value) results = opt.solve(blk, tee=stee) blk.pressure_equality_constraints.activate() for t in blk.flowsheet().config.time: blk.mixed_state[t].pressure.unfix() else: results = opt.solve(blk, tee=stee) if outlvl > 0: if results.solver.termination_condition == \ TerminationCondition.optimal: _log.info('{} Initialisation Complete.'.format(blk.name)) else: _log.warning('{} Initialisation Failed.'.format(blk.name)) else: _log.info('{} Initialisation Complete.'.format(blk.name)) if hold_state is True: return flags else: blk.release_state(flags, outlvl=outlvl - 1)
Author: Jaffer Ghouse """ import pytest from pyomo.environ import ConcreteModel, SolverFactory, TerminationCondition, \ SolverStatus, value from pyomo.util.check_units import assert_units_consistent from idaes.core import FlowsheetBlock from idaes.generic_models.properties.activity_coeff_models.BTX_activity_coeff_VLE \ import BTXParameterBlock from idaes.core.util.model_statistics import degrees_of_freedom # See if ipopt is available and set up solver if SolverFactory('ipopt').available(): solver = SolverFactory('ipopt') solver.options = {'tol': 1e-6, 'mu_init': 1e-8, 'bound_push': 1e-8} else: solver = None # ----------------------------------------------------------------------------- # Create a flowsheet for test m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) # vapor-liquid (ideal) - FTPz m.fs.properties_ideal_vl_FTPz = BTXParameterBlock( default={ "valid_phase": ('Liq', 'Vap'), "activity_coeff_model": "Ideal", "state_vars": "FTPz" }) m.fs.state_block_ideal_vl_FTPz = m.fs.properties_ideal_vl_FTPz.build_state_block(
def initialize(blk, state_args_PA=None, state_args_SA=None, outlvl=idaeslog.NOTSET, solver='ipopt', optarg={'tol': 1e-6}): ''' Initialization routine. 1.- initialize state blocks, using an initial guess for inlet primary air and secondary air. 2.- Use PA and SA values to guess flue gas component molar flowrates, Temperature, and Pressure. Initialize flue gas state block. 3.- Then, solve complete model. Keyword Arguments: state_args_PA : a dict of arguments to be passed to the property package(s) for the primary air state block to provide an initial state for initialization (see documentation of the specific property package) (default = None). state_args_SA : a dict of arguments to be passed to the property package(s) for secondary air state block to provide an initial state for initialization (see documentation of the specific property package) (default = None). outlvl : sets output level of initialisation routine optarg : solver options dictionary object (default={'tol': 1e-6}) solver : str indicating whcih solver to use during initialization (default = 'ipopt') Returns: None ''' init_log = idaeslog.getInitLogger(blk.name, outlvl, tag="unit") solve_log = idaeslog.getSolveLogger(blk.name, outlvl, tag="unit") opt = SolverFactory(solver) opt.options = optarg # --------------------------------------------------------------------- # Initialize inlet property blocks blk.primary_air.initialize( outlvl=outlvl, optarg=optarg, solver=solver, state_args=state_args_PA ) blk.primary_air_moist.initialize( outlvl=outlvl, optarg=optarg, solver=solver, state_args=state_args_PA ) blk.secondary_air.initialize( outlvl=outlvl, optarg=optarg, solver=solver, state_args=state_args_SA ) init_log.info_high("Initialization Step 1 Complete.") state_args = {"flow_mol_comp": {"H2O": (blk.primary_air_inlet. flow_mol_comp[0, "H2O"].value + blk.secondary_air_inlet. flow_mol_comp[0, "H2O"].value), "CO2": (blk.primary_air_inlet. flow_mol_comp[0, "CO2"].value + blk.secondary_air_inlet. flow_mol_comp[0, "CO2"].value), "N2": (blk.primary_air_inlet. flow_mol_comp[0, "N2"].value + blk.secondary_air_inlet. flow_mol_comp[0, "N2"].value), "O2": (blk.primary_air_inlet. flow_mol_comp[0, "O2"].value + blk.secondary_air_inlet. flow_mol_comp[0, "O2"].value), "SO2": (blk.primary_air_inlet. flow_mol_comp[0, "SO2"].value + blk.secondary_air_inlet. flow_mol_comp[0, "SO2"].value), "NO": (blk.primary_air_inlet. flow_mol_comp[0, "NO"].value + blk.secondary_air_inlet. flow_mol_comp[0, "NO"].value)}, "temperature": 1350.00, "pressure": blk.primary_air_inlet.pressure[0].value} # initialize flue gas outlet blk.flue_gas.initialize(state_args=state_args, outlvl=outlvl, solver=solver) init_log.info_high("Initialization Step 2 Complete.") if blk.config.calculate_PA_SA_flows is False: # Option 1: given PA and SA component flow rates - fixed inlets # fix inlet component molar flow rates # unfix ratio_PA2coal, SR, and fluegas_o2_pct_dry blk.primary_air_inlet.flow_mol_comp[...].fix() blk.secondary_air_inlet.flow_mol_comp[...].fix() blk.ratio_PA2coal.unfix() blk.SR.unfix() blk.fluegas_o2_pct_dry.unfix() dof = degrees_of_freedom(blk) else: # Option 2: SR, ratioPA2_coal to estimate TCA, PA, SA # unfix component molar flow rates, but keep T and P fixed. blk.primary_air_inlet.flow_mol_comp[:, :].unfix() blk.secondary_air_inlet.flow_mol_comp[:, :].unfix() dof = degrees_of_freedom(blk) if not dof == 0: raise ConfigurationError('User needs to check ' 'degrees of freedom') 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)) ) init_log.info("Initialization Complete.")
def initialize(blk, outlvl=6, optarg={}, solver="ipopt", hold_state=False): """ Initialization routine for mixer (default solver ipopt) Keyword Arguments: outlvl : sets output level of initialization routine optarg : solver options dictionary object (default={}) 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. **Valid values:** **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. """ init_log = idaeslog.getInitLogger(blk.name, outlvl, tag="unit") solve_log = idaeslog.getSolveLogger(blk.name, outlvl, tag="unit") # Set solver options opt = SolverFactory(solver) opt.options = optarg # Initialize inlet state blocks flags = {} inlet_list = blk.create_inlet_list() i_block_list = [] for i in inlet_list: i_block = getattr(blk, i + "_state") i_block_list.append(i_block) flags[i] = {} flags[i] = i_block.initialize( outlvl=outlvl, optarg=optarg, solver=solver, hold_state=True, ) # Initialize mixed state block if blk.config.mixed_state_block is None: mblock = blk.mixed_state else: mblock = blk.config.mixed_state_block o_flags = {} # Calculate initial guesses for mixed stream state for t in blk.flowsheet().config.time: # Iterate over state vars as defined by property package s_vars = mblock[t].define_state_vars() for s in s_vars: i_vars = [] for k in s_vars[s]: # Record whether variable was fixed or not o_flags[t, s, k] = s_vars[s][k].fixed # If fixed, use current value # otherwise calculate guess from mixed state if not s_vars[s][k].fixed: for i in range(len(i_block_list)): i_vars.append( getattr(i_block_list[i][t], s_vars[s].local_name) ) if s == "pressure": # If pressure, use minimum as initial guess mblock[t].pressure.value = min( i_block_list[i][t].pressure.value for i in range(len(i_block_list)) ) elif "flow" in s: # If a "flow" variable (i.e. extensive), sum inlets for k in s_vars[s]: s_vars[s][k].value = sum( i_vars[i][k].value for i in range( len(i_block_list)) ) else: # Otherwise use average of inlets for k in s_vars[s]: s_vars[s][k].value = sum( i_vars[i][k].value for i in range( len(i_block_list)) ) / len(i_block_list) mblock.initialize( outlvl=outlvl, optarg=optarg, solver=solver, hold_state=False, ) # Revert fixed status of variables to what they were before for t in blk.flowsheet().config.time: s_vars = mblock[t].define_state_vars() for s in s_vars: for k in s_vars[s]: s_vars[s][k].fixed = o_flags[t, s, k] if blk.config.mixed_state_block is None: if ( hasattr(blk, "pressure_equality_constraints") and blk.pressure_equality_constraints.active is True ): blk.pressure_equality_constraints.deactivate() for t in blk.flowsheet().config.time: sys_press = getattr( blk, blk.create_inlet_list()[0] + "_state")[t].pressure blk.mixed_state[t].pressure.fix(sys_press.value) with idaeslog.solver_log(solve_log, idaeslog.DEBUG)as slc: res = opt.solve(blk, tee=slc.tee) blk.pressure_equality_constraints.activate() for t in blk.flowsheet().config.time: blk.mixed_state[t].pressure.unfix() else: with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: res = opt.solve(blk, tee=slc.tee) init_log.info( "Initialization Complete: {}".format(idaeslog.condition(res)) ) else: init_log.info("Initialization Complete.") if hold_state is True: return flags else: blk.release_state(flags, outlvl=outlvl)
def initialize( blk, shell_state_args=None, tube_state_args=None, outlvl=idaeslog.NOTSET, solver="ipopt", optarg={"tol": 1e-6}, ): """ Initialization routine for the 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={'tol': 1e-6}) solver : str indicating whcih solver to use during initialization (default = 'ipopt') Returns: None """ init_log = idaeslog.getInitLogger(blk.name, outlvl, tag="unit") solve_log = idaeslog.getSolveLogger(blk.name, outlvl, tag="unit") opt = SolverFactory(solver) opt.options = optarg # --------------------------------------------------------------------- # Initialize shell block flags_shell = blk.shell.initialize( outlvl=outlvl, optarg=optarg, solver=solver, state_args=shell_state_args, ) flags_tube = blk.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 blk.config.has_wall_conduction == WallConductionType.zero_dimensional: shell_units = \ blk.config.shell_side.property_package.get_metadata().get_derived_units for t in blk.flowsheet().config.time: for z in blk.shell.length_domain: blk.temperature_wall[t, z].fix( value(0.5 * (blk.shell.properties[t, 0].temperature + pyunits.convert( blk.tube.properties[t, 0].temperature, to_units=shell_units('temperature'))))) blk.tube.deactivate() blk.tube_heat_transfer_eq.deactivate() blk.wall_0D_model.deactivate() with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: res = opt.solve(blk, tee=slc.tee) init_log.info_high("Initialization Step 2 {}.".format( idaeslog.condition(res))) blk.tube.activate() blk.tube_heat_transfer_eq.activate() 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))) blk.wall_0D_model.activate() blk.temperature_wall.unfix() with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: res = opt.solve(blk, tee=slc.tee) init_log.info_high("Initialization Step 4 {}.".format( idaeslog.condition(res))) blk.shell.release_state(flags_shell) blk.tube.release_state(flags_tube) init_log.info("Initialization Complete.")
"energy_mixing_type": MixingType.extensive, "momentum_mixing_type": MomentumMixingType.none }) m.fs.Mixer.feed_1.flow_mass[0].fix(0.5) m.fs.Mixer.feed_1.mass_frac[0].fix(0.1) m.fs.Mixer.feed_1.temperature[0].fix(273.15 + 50) m.fs.Mixer.feed_2.flow_mass[0].fix(0.5) m.fs.Mixer.feed_2.mass_frac[0].fix(0.035) m.fs.Mixer.feed_2.temperature[0].fix(273.15 + 25) # m.fs.Mixer.outlet.temperature[0].fix(273.15 + 40) # m.fs.Mixer.mixed_state[0].dens_mass # m.fs.Mixer.mixed_state[0].viscosity # m.fs.Mixer.mixed_state[0].dens_mass_comp m.fs.Mixer.mixed_state[0].pressure_osm # m.fs.Mixer.mixed_state[0].osm_coeff # m.fs.Mixer.mixed_state[0].enth_mass_liq m.fs.Mixer.initialize(outlvl=0) print("Degrees of Freedom =", degrees_of_freedom(m)) assert degrees_of_freedom(m) == 0 solver = SolverFactory('ipopt') solver.options = {'tol': 1e-6, 'max_iter': 5000} results = solver.solve(m, tee=False) assert results.solver.termination_condition == TerminationCondition.optimal # m.display() # m.fs.Mixer.display() for p in m.fs.Mixer.component_objects(Port, descend_into=True): p.display() # m.fs.Mixer.pprint()
from collections import OrderedDict import random import time as timemodule import enum import pdb __author__ = "Robert Parker and David Thierry" # TODO: clean up this file - add license, remove solver_available # See if ipopt is available and set up solver solver_available = SolverFactory('ipopt').available() if solver_available: solver = SolverFactory('ipopt') solver.options = {'tol': 1e-6, 'mu_init': 1e-8, 'bound_push': 1e-8, 'halt_on_ampl_error': 'yes'} else: solver = None class CachedVarsContext(object): def __init__(self, varlist, nvars, tlist): if type(tlist) is not list: tlist = [tlist] self.n_t = len(tlist) self.vars = varlist self.nvars = nvars self.tlist = tlist self.cache = [[None for j in range(self.n_t)] for i in range(self.nvars)]
def initialize(blk, outlvl=0, optarg={}, solver='ipopt', hold_state=False): ''' Initialisation routine for separator (default solver ipopt) Keyword Arguments: outlvl : sets output level of initialisation routine. **Valid values:** **0** - no output (default), **1** - return solver state for each step in routine, **2** - include solver output infomation (tee=True) 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. **Valid values:** **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. ''' # Set solver options if outlvl > 1: stee = True else: stee = False opt = SolverFactory(solver) opt.options = optarg # Initialize mixed state block if blk.config.mixed_state_block is not None: mblock = blk.config.mixed_state_block else: mblock = blk.mixed_state flags = mblock.initialize(outlvl=outlvl - 1, optarg=optarg, solver=solver, hold_state=True) if blk.config.ideal_separation: # If using ideal splitting, initialisation should be complete return flags # Initialize outlet StateBlocks outlet_list = blk.create_outlet_list() for o in outlet_list: # Get corresponding outlet StateBlock o_block = getattr(blk, o + "_state") for t in blk.flowsheet().config.time: # Calculate values for state variables s_vars = o_block[t].define_state_vars() for v in s_vars: m_var = getattr(mblock[t], s_vars[v].local_name) if "flow" in v: # If a "flow" variable, is extensive # Apply split fraction try: for k in s_vars[v]: if (k is None or blk.config.split_basis == SplittingType.totalFlow): s_vars[v][k].value = value( m_var[k] * blk.split_fraction[(t, o)]) else: s_vars[v][k].value = value( m_var[k] * blk.split_fraction[(t, o) + k]) except KeyError: raise KeyError( "{} state variable and split fraction " "indexing sets do not match. The in-built" " initialization routine for Separators " "relies on the split fraction and state " "variable indexing sets matching to " "calculate initial guesses for extensive " "variables. In other cases users will " "need to provide their own initial " "guesses".format(blk.name)) else: # Otherwise intensive, equate to mixed stream for k in s_vars[v]: s_vars[v][k].value = m_var[k].value # Call initialization routine for outlet StateBlock o_block.initialize(outlvl=outlvl - 1, optarg=optarg, solver=solver, hold_state=False) if blk.config.mixed_state_block is None: results = opt.solve(blk, tee=stee) if outlvl > 0: if results.solver.termination_condition == \ TerminationCondition.optimal: _log.info('{} Initialisation Complete.'.format(blk.name)) else: _log.warning('{} Initialisation Failed.'.format(blk.name)) else: _log.info('{} Initialisation Complete.'.format(blk.name)) if hold_state is True: return flags else: blk.release_state(flags, outlvl=outlvl - 1)
def initialize(blk, state_args_feedwater={}, state_args_water_steam={}, outlvl=idaeslog.NOTSET, solver='ipopt', optarg={'tol': 1e-6}): ''' Drum initialization routine. Keyword Arguments: state_args : a dict of arguments to be passed to the property package(s) for the control_volume of the model to provide an initial state for initialization (see documentation of the specific property package) (default = None). outlvl : sets output level of initialisation routine * 0 = no output (default) * 1 = return solver state for each step in routine * 2 = return solver state for each step in subroutines * 3 = include solver output infomation (tee=True) optarg : solver options dictionary object (default={'tol': 1e-6}) solver : str indicating whcih solver to use during initialization (default = 'ipopt') Returns: None ''' init_log = idaeslog.getInitLogger(blk.name, outlvl, tag="unit") solve_log = idaeslog.getSolveLogger(blk.name, outlvl, tag="unit") opt = SolverFactory(solver) opt.options = optarg init_log.info_low("Starting initialization...") # fix FeedWater Inlet flags_fw = fix_state_vars(blk.mixer.FeedWater_state, state_args_feedwater) # expecting 2 DOF due to pressure driven constraint if degrees_of_freedom(blk) != 2: raise Exception(degrees_of_freedom(blk)) blk.flash.initialize(state_args_water_steam=state_args_water_steam, outlvl=outlvl, optarg=optarg, solver=solver) init_log.info("Initialization Step 1 Complete.") blk.mixer.SaturatedWater.flow_mol[:].fix(blk.flash.liq_outlet. flow_mol[0].value) blk.mixer.SaturatedWater.pressure[:].fix(blk.flash.liq_outlet. pressure[0].value) blk.mixer.SaturatedWater.enth_mol[:].fix(blk.flash.liq_outlet. enth_mol[0].value) blk.mixer.initialize(outlvl=outlvl, optarg=optarg, solver=solver) init_log.info("Initialization Step 2 Complete.") blk.control_volume.initialize(outlvl=outlvl, optarg=optarg, solver=solver, hold_state=False) init_log.info("Initialization Step 3 Complete.") # fix flash Inlet flags_steam = fix_state_vars(blk.flash.mixed_state, state_args_water_steam) # unfix inlets (connected with arc) blk.mixer.SaturatedWater.flow_mol[:].unfix() blk.mixer.SaturatedWater.enth_mol[:].unfix() blk.mixer.SaturatedWater.pressure[:].unfix() blk.mixer.FeedWater.pressure[0].unfix() # solve model with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc: res = opt.solve(blk, tee=slc.tee) init_log.info_high( "Initialization Step 4 {}.".format(idaeslog.condition(res)) ) revert_state_vars(blk.mixer.FeedWater_state, flags_fw) revert_state_vars(blk.flash.mixed_state, flags_steam) init_log.info("Initialization Complete.")