def test_P_sweep(self): m = ConcreteModel() m.fs = FlowsheetBlock(default={'dynamic': False}) m.fs.props = BT_PR.BTParameterBlock( default={'valid_phase': ('Vap', 'Liq')}) m.fs.state = m.fs.props.build_state_block( default={'defined_state': True}) for T in range(370, 500, 25): m.fs.state.flow_mol.fix(100) m.fs.state.mole_frac_comp["benzene"].fix(0.5) m.fs.state.mole_frac_comp["toluene"].fix(0.5) m.fs.state.temperature.fix(T) m.fs.state.pressure.fix(1e5) m.fs.state.initialize() results = solver.solve(m) assert check_optimal_termination(results) while m.fs.state.pressure.value <= 1e6: m.fs.state.pressure.value = m.fs.state.pressure.value + 1e5 results = solver.solve(m) assert check_optimal_termination(results) print(T, m.fs.state.pressure.value)
def test_P_sweep(self, m): for T in range(300, 1000, 200): m.fs.state[1].flow_mol.fix(100) m.fs.state[1].mole_frac_comp["H2"].fix(0.1) m.fs.state[1].mole_frac_comp["CO"].fix(0.1) m.fs.state[1].mole_frac_comp["H2O"].fix(0.1) m.fs.state[1].mole_frac_comp["CO2"].fix(0.1) m.fs.state[1].mole_frac_comp["O2"].fix(0.1) m.fs.state[1].mole_frac_comp["N2"].fix(0.1) m.fs.state[1].mole_frac_comp["Ar"].fix(0.1) m.fs.state[1].mole_frac_comp["CH4"].fix(0.1) m.fs.state[1].mole_frac_comp["C2H6"].fix(0.1) m.fs.state[1].mole_frac_comp["C3H8"].fix(0.05) m.fs.state[1].mole_frac_comp["C4H10"].fix(0.05) m.fs.state[1].temperature.fix(T) m.fs.state[1].pressure.fix(1e5) m.fs.state.initialize() results = solver.solve(m) assert check_optimal_termination(results) while m.fs.state[1].pressure.value <= 1e6: m.fs.state[1].pressure.value = (m.fs.state[1].pressure.value + 2e5) results = solver.solve(m) assert check_optimal_termination(results) assert -70000 >= value(m.fs.state[1].enth_mol_phase['Vap']) assert -105000 <= value(m.fs.state[1].enth_mol_phase['Vap']) assert 185 <= value(m.fs.state[1].entr_mol_phase['Vap']) assert 265 >= value(m.fs.state[1].entr_mol_phase['Vap'])
def test_solve(self, btx_ftpz, btx_fctp): results = solver.solve(btx_ftpz) assert check_optimal_termination(results) results = solver.solve(btx_fctp) assert check_optimal_termination(results)
def test_solve(self, m): m.SOFC.current_density.fix(4000) m.SOFC.fuel_temperature.fix(348.3) m.SOFC.internal_reforming.fix(0.6) m.SOFC.air_temperature.fix(617.3) m.SOFC.air_recirculation.fix(0.5) m.SOFC.OTC.fix(2.1) m.SOFC.fuel_util.fix(0.8) m.SOFC.air_util.fix(0.449) m.SOFC.pressure.fix(1) assert degrees_of_freedom(m) == 0 results = solver.solve(m) assert check_optimal_termination(results) assert (pytest.approx(705.5, abs=1e-1) == value( m.SOFC.anode_outlet_temperature)) assert (pytest.approx(726.3, abs=1e-1) == value( m.SOFC.cathode_outlet_temperature)) assert (pytest.approx(0.867, abs=1e-3) == value(m.SOFC.stack_voltage)) assert (pytest.approx(749.1, abs=1e-1) == value(m.SOFC.max_cell_temperature)) assert (pytest.approx(99.9, abs=1e-1) == value(m.SOFC.deltaT_cell))
def test_run_unit(build_unit): m = build_unit assert degrees_of_freedom(m) == 0 optarg = {"tol": 1e-6, "linear_solver": "ma27", "max_iter": 40} solver.options = optarg # solve model results = solver.solve(m, tee=True) # Check for optimal solution assert pyo.check_optimal_termination(results) # energy balance assert (pytest.approx(0, abs=1e-3) == pyo.value( m.fs.unit.tube_inlet.flow_mol[0] * m.fs.unit.tube_inlet.enth_mol[0] + sum(m.fs.unit.shell_inlet.flow_mol_comp[0, i] for i in m.fs.unit.shell.config.property_package.component_list) * m.fs.unit.shell.properties[0, 0].enth_mol - m.fs.unit.tube_outlet.flow_mol[0] * m.fs.unit.tube_outlet.enth_mol[0] - sum(m.fs.unit.shell_outlet.flow_mol_comp[0, i] for i in m.fs.unit.shell.config.property_package.component_list) * m.fs.unit.shell.properties[0, 1].enth_mol)) # pressure drop assert (pytest.approx(100134.3247, abs=1e-3) == pyo.value( m.fs.unit.shell.properties[0, 1].pressure)) # mass balance assert (pytest.approx(0, abs=1e-3) == pyo.value( sum(m.fs.unit.shell_inlet.flow_mol_comp[0, i] for i in m.fs.unit.shell.config.property_package.component_list) + m.fs.unit.tube_inlet.flow_mol[0] - m.fs.unit.tube_outlet.flow_mol[0] - sum(m.fs.unit.shell_outlet.flow_mol_comp[0, i] for i in m.fs.unit.shell.config.property_package.component_list)))
def check_solve(results, checkpoint=None, logger=_log, fail_flag=False): """ Check that solver termination is optimal and OK in an initialization routine. If the check fails, proceed through initialization with only a logger warning by default, or set fail_flag=True to raise an error. This should also work for checking a solve outside of an initialization routine. Keyword Arguments: results : solver results checkpoint : Optional string argument to specify the step of initialization being checked (e.g., checkpoint="Initialization step 1: solve indexed blocks") logger : Optional argument for loading idaes.getInitLogger object (e.g., logger=init_log) fail_flag : Boolean argument to specify error or warning (Default: fail_flag=False produces logger warning. set fail_flag=True to raise an error and stop the initialization routine.) Returns: None """ if check_optimal_termination(results): if checkpoint is None: logger.info(f'Solve successful.') else: logger.info(f'{checkpoint} successful.') else: if checkpoint is None: msg = f"The solver failed to converge to an optimal solution. " \ f"This suggests that the user provided infeasible inputs or that the model is poorly scaled." else: msg = f"{checkpoint} failed. The solver failed to converge to an optimal solution. " \ f"This suggests that the user provided infeasible inputs or that the model is poorly scaled." if fail_flag: logger.error(msg) raise ValueError(msg) else: logger.warning(msg)
def test_ASU_costing(): # Create a Concrete Model as the top level object m = pyo.ConcreteModel() # Add a flowsheet object to the model m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.get_costing(year='2017') m.fs.ASU = pyo.Block() m.fs.ASU.O2_flow = pyo.Var() m.fs.ASU.O2_flow.fix(13078) # TPD get_ASU_cost(m.fs.ASU, m.fs.ASU.O2_flow) # try solving solver = get_solver() results = solver.solve(m, tee=True) assert pyo.check_optimal_termination(results) m.fs.ASU.costing.bare_erected_cost.display() assert pytest.approx(pyo.value(m.fs.ASU.costing.bare_erected_cost), abs=1) == 3.2675e6 / 1e3 return m
def test_initialize(): # Speed this up by using a simpler composition and reaction set comps = {"CH4", "O2", "H2O", "CO2", "N2", "Ar"} rxns = {"ch4_cmb": "CH4"} phases = ["Vap"] air_comp = { "O2": 0.2074, "H2O": 0.0099, "CO2": 0.0003, "N2": 0.7732, "Ar": 0.0092 } ng_comp = { # simplified composition to make it run faster "CH4": 1.0, "O2": 0.0, "H2O": 0.0, "CO2": 0.0, "N2": 0.0, "Ar": 0.0 } with idaes.temporary_config_ctx(): use_idaes_solver_configuration_defaults() idaes.cfg.ipopt["options"]["nlp_scaling_method"] = "user-scaling" idaes.cfg.ipopt["options"]["bound_push"] = 1e-6 m, solver = main(comps=comps, rxns=rxns, phases=phases, air_comp=air_comp, ng_comp=ng_comp, initialize=True) res = run_full_load(m, solver) assert pyo.check_optimal_termination(res)
def test_subsaturated(self, model): assert model.state[0].phase_component_set == [ ("Liq", "H2O"), ("Liq", "Na+"), ("Liq", "Cl-"), ("Sol", "NaCl")] model.state[0].temperature.fix(298.15) model.state[0].pressure.fix(101325) # For subsaturated systems, fix the Na and Cl flows and check that no # solid is formed. model.state[0].flow_mol_phase_comp["Liq", "H2O"].fix(55.56) model.state[0].flow_mol_phase_comp["Liq", "Na+"].fix(0) model.state[0].flow_mol_phase_comp["Liq", "Cl-"].fix(0) model.state[0].flow_mol_phase_comp["Sol", "NaCl"].set_value(0) for i in range(11): for j in range(11): if i*j < 40: # Zeroes result in evaluation errors, so use a small number if i == 0: i = 1e-8 if j == 0: j = 1e-8 model.state[0].flow_mol_phase_comp["Liq", "Na+"].fix(i) model.state[0].flow_mol_phase_comp["Liq", "Cl-"].fix(j) results = solver.solve(model) assert check_optimal_termination(results) assert pytest.approx(0, abs=1e-5) == value( model.state[0].flow_mol_phase_comp["Sol", "NaCl"])
def test_saturated(self, model): assert model.state[0].phase_component_set == [ ("Liq", "H2O"), ("Liq", "Na+"), ("Liq", "Cl-"), ("Sol", "NaCl")] model.state[0].temperature.fix(298.15) model.state[0].pressure.fix(101325) # Solve for saturated states (i.e. solubility product applied) by # fixing the flowrate of solids to a positive value. # Then start with a large amount of Na+ and solve for the flowrate of # Cl- which satisfies the solubility product (ignore electroneutrality) model.state[0].flow_mol_phase_comp["Liq", "H2O"].fix(55.56) model.state[0].flow_mol_phase_comp["Liq", "Na+"].fix(20) model.state[0].flow_mol_phase_comp["Liq", "Cl-"].set_value(2.5) model.state[0].flow_mol_phase_comp["Sol", "NaCl"].fix(1) for i in range(20, 2, -1): model.state[0].flow_mol_phase_comp["Liq", "Na+"].fix(i) results = solver.solve(model) assert check_optimal_termination(results) assert pytest.approx(8.235e-3, abs=1e-8) == value( model.state[0].mole_frac_phase_comp["Liq", "Na+"] * model.state[0].mole_frac_phase_comp["Liq", "Cl-"])
def test_T_sweep(self): m = ConcreteModel() m.fs = FlowsheetBlock(default={'dynamic': False}) m.fs.props = BT_PR.BTParameterBlock( default={'valid_phase': ('Vap', 'Liq')}) m.fs.state = m.fs.props.build_state_block( default={"defined_state": True}) m.fs.obj = Objective(expr=(m.fs.state.temperature - 510)**2) for logP in range(8, 13, 1): m.fs.obj.deactivate() m.fs.state.flow_mol.fix(100) m.fs.state.mole_frac_comp["benzene"].fix(0.5) m.fs.state.mole_frac_comp["toluene"].fix(0.5) m.fs.state.temperature.fix(300) m.fs.state.pressure.fix(10**(0.5*logP)) m.fs.state.initialize() m.fs.state.temperature.unfix() m.fs.obj.activate() results = solver.solve(m, tee=True) assert check_optimal_termination(results) assert m.fs.state.flow_mol_phase["Liq"].value <= 1e-5
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 pyo.check_optimal_termination(results) assert (pytest.approx(pyo.value(m.fs.unit.costing.purchase_cost), abs=1e-2) == 962795.521) # Example 22.1 Ref Book
def test_solve_unit(build_unit): m = build_unit m.fs.unit.inlet.enth_mol.fix() m.fs.unit.inlet.flow_mol.fix() m.fs.unit.inlet.pressure.fix() assert degrees_of_freedom(m) == 0 results = solver.solve(m, tee=True) # Check for optimal solution assert pyo.check_optimal_termination(results) # check material balance assert (pytest.approx(pyo.value(m.fs.unit.control_volume.properties_in[0]. flow_mol - m.fs.unit.control_volume. properties_out[0].flow_mol), abs=1e-3) == 0) # pressure drop assert (pytest.approx(-224074.4039, abs=1e-3) == pyo.value(m.fs.unit. deltaP[0])) # check energy balance assert (pytest.approx( pyo.value(m.fs.unit.control_volume.properties_in[0].enth_mol - m.fs.unit.control_volume.properties_out[0].enth_mol), abs=1e-3) == 0)
def test_init(model): # check that the model solved properly and has 0 degrees of freedom assert (degrees_of_freedom(model) == 0) model.fs.drum.feedwater_inlet.flow_mol[:].fix() model.fs.drum.feedwater_inlet.pressure[:].unfix() model.fs.drum.feedwater_inlet.enth_mol[:].fix() optarg = {"tol": 1e-6, "max_iter": 20} solver.options = optarg # set scaling parameters for i in model.fs.ww_zones: iscale.set_scaling_factor(model.fs.Waterwalls[i].heat_flux_conv[0], 1e-5) iscale.calculate_scaling_factors(model) results = solver.solve(model, tee=True) assert pyo.check_optimal_termination(results) assert (pyo.value(model.fs.downcomer.deltaP[0]) > 0) assert (pytest.approx(0, abs=1e-3) == pyo.value( model.fs.Waterwalls[10].control_volume.properties_out[0].flow_mol - model.fs.Waterwalls[1].control_volume.properties_in[0].flow_mol)) assert (pyo.value(model.fs.drum.feedwater_inlet.flow_mol[0] - model.fs.drum.steam_outlet.flow_mol[0]) == pytest.approx( 0, abs=1e-3))
def test_solve_vle(self, model): results = solver.solve(model) # Check for optimal solution assert check_optimal_termination(results) assert pytest.approx(365.35, abs=0.01) == value( model.props[1].temperature_bubble[("Vap", "Liq")]) assert pytest.approx(0.7137, abs=1e-4) == value( model.props[1]._mole_frac_tbub[("Vap", "Liq", "A")]) assert pytest.approx(0.2863, abs=1e-4) == value( model.props[1]._mole_frac_tbub[("Vap", "Liq", "B")]) assert pytest.approx(372.02, abs=0.01) == value( model.props[1].temperature_dew[("Vap", "Liq")]) assert pytest.approx(0.2909, abs=1e-4) == value( model.props[1]._mole_frac_tdew[("Vap", "Liq", "A")]) assert pytest.approx(0.7091, abs=1e-4) == value( model.props[1]._mole_frac_tdew[("Vap", "Liq", "B")]) assert pytest.approx(109479, abs=1) == value( model.props[1].pressure_bubble[("Vap", "Liq")]) assert pytest.approx(0.7119, abs=1e-4) == value( model.props[1]._mole_frac_pbub[("Vap", "Liq", "A")]) assert pytest.approx(0.2881, abs=1e-4) == value( model.props[1]._mole_frac_pbub[("Vap", "Liq", "B")]) assert pytest.approx(89820, abs=1) == value( model.props[1].pressure_dew[("Vap", "Liq")]) assert pytest.approx(0.2881, abs=1e-4) == value( model.props[1]._mole_frac_pdew[("Vap", "Liq", "A")]) assert pytest.approx(0.7119, abs=1e-4) == value( model.props[1]._mole_frac_pdew[("Vap", "Liq", "B")])
def test_T_sweep(self, m): assert_units_consistent(m) m.fs.obj = Objective(expr=(m.fs.state[1].temperature - 510)**2) for logP in range(8, 13, 1): m.fs.state[1].flow_mol.fix(100) m.fs.state[1].mole_frac_comp["H2"].fix(0.1) m.fs.state[1].mole_frac_comp["CO"].fix(0.1) m.fs.state[1].mole_frac_comp["H2O"].fix(0.1) m.fs.state[1].mole_frac_comp["CO2"].fix(0.1) m.fs.state[1].mole_frac_comp["O2"].fix(0.1) m.fs.state[1].mole_frac_comp["N2"].fix(0.1) m.fs.state[1].mole_frac_comp["Ar"].fix(0.1) m.fs.state[1].mole_frac_comp["CH4"].fix(0.1) m.fs.state[1].mole_frac_comp["C2H6"].fix(0.1) m.fs.state[1].mole_frac_comp["C3H8"].fix(0.05) m.fs.state[1].mole_frac_comp["C4H10"].fix(0.05) m.fs.state[1].temperature.fix(300) m.fs.state[1].pressure.fix(10**(0.5 * logP)) m.fs.state.initialize() m.fs.state[1].temperature.unfix() results = solver.solve(m, tee=True) assert check_optimal_termination(results) assert -93000 == pytest.approx( value(m.fs.state[1].enth_mol_phase['Vap']), 1) assert 250 == pytest.approx( value(m.fs.state[1].entr_mol_phase['Vap']), 1)
def get_reference_entropy(comp): m = ConcreteModel() m.params = GenericParameterBlock(default=_get_prop([comp])) m.props = m.params.state_block_class( default={ "defined_state": True, "parameters": m.params, "has_phase_equilibrium": False }) # Want to make sure intermediate quantities are constructed before we # solve the block. Therefore introduce this variable and constraint m.S_ref = Var(domain=Reals, initialize=1, units=pyunits.J / pyunits.mol) def rule_S_ref(blk, j): return m.S_ref == m.props.entr_mol m.S_ref_eq = Constraint(m.params.component_list, rule=rule_S_ref) m.props.mole_frac_comp[comp].fix(1) m.props.temperature.fix(standard_temp) m.props.pressure.fix(standard_pressure) solver = SolverFactory('ipopt') results = solver.solve(m) assert check_optimal_termination(results) assert (value(m.S_ref) == approx(value(m.props.entr_mol_phase_comp["Vap", comp]), rel=1E-12)) return value(m.S_ref)
def test_run(build_unit): m = build_unit optarg = {"tol": 1e-7, "linear_solver": "ma27", "max_iter": 50} solver.options = optarg # solve model results = solver.solve(m, tee=True) # Check for optimal solution assert pyo.check_optimal_termination(results) assert degrees_of_freedom(m) == 0 # energy balance assert (pytest.approx(0, abs=1e-3) == pyo.value(m.fs.unit.inlet.flow_mol[0] * m.fs.unit.inlet.enth_mol[0] - m.fs.unit.outlet.flow_mol[0] * m.fs.unit.outlet.enth_mol[0] + m.fs.unit.work_mechanical[0])) # pressure change assert (pytest.approx(143651.0, abs=0.1) == pyo.value(m.fs.unit.deltaP[0])) # mass balance assert (pytest.approx(0, abs=1e-2) == pyo.value(m.fs.unit.inlet.flow_mol[0] - m.fs.unit.outlet.flow_mol[0] ))
def build_model(): m = ConcreteModel() # Properties comp_props = get_prop(components=["CO2", "H2O"], phases=["Vap", "Liq"]) # Parameters block m.params = GenericParameterBlock(default=comp_props) m.props = m.params.build_state_block( default={ "defined_state": True, "parameters": m.params, "has_phase_equilibrium": True }) m.props.flow_mol.fix(100) m.props.pressure.fix(101325) m.props.mole_frac_comp["CO2"].fix(0.94) m.props.mole_frac_comp["H2O"].fix(0.06) m.props.temperature_constraint = Constraint( expr=m.props.temperature == m.props.temperature_dew["Vap", "Liq"]) assert degrees_of_freedom(m) == 0 m.props.initialize(state_vars_fixed=True) results = get_solver(options={"bound_push": 1e-8}).solve(m) assert check_optimal_termination(results) return m
def test_SFIL3(self, model): model.props[1].flow_mol.fix(1) model.props[1].temperature.fix(92.88) model.props[1].pressure.fix(353140) model.props[1].mole_frac_comp["nitrogen"].fix(0.6653) model.props[1].mole_frac_comp["argon"].fix(0.0140) model.props[1].mole_frac_comp["oxygen"].fix(0.3207) assert degrees_of_freedom(model.props[1]) == 0 orig_fixed_vars = fixed_variables_set(model) orig_act_consts = activated_constraints_set(model) model.props.initialize(optarg={'tol': 1e-6}) assert degrees_of_freedom(model) == 0 results = solver.solve(model) # Check for optimal solution assert check_optimal_termination(results) assert model.props[1].mole_frac_phase_comp["Liq", "nitrogen"].value == \ pytest.approx(0.6653, abs=1e-3) assert model.props[1].phase_frac["Vap"].value == \ pytest.approx(0.0, abs=1e-3) assert value(model.props[1].enth_mol_phase["Liq"]) == \ pytest.approx(-11662.4, abs=1e1)
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.") solverobj = get_solver(solver, optarg) if state_args is None: state_args = {} state_dict = (self.control_volume.properties_in[ self.flowsheet().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 = solverobj.solve(self, tee=slc.tee) init_log.info("Initialization Complete, {}.".format( idaeslog.condition(res))) if not check_optimal_termination(res): raise InitializationError( f"{self.name} failed to initialize successfully. Please check " f"the output logs for more information.") self.control_volume.release_state(flags=flags)
def test_units1_costing(build_costing): m = build_costing # Accounts with Feedwater Flow to HP section of HRSG, as the # reference/scaling parameter - Exhibit 5-15 FW_accounts = ['3.1', '3.3', '8.4'] # Accounts with Raw water withdrawal as the reference/scaling parameter # Exhibit 5-14 RW_withdraw_accounts = ['3.2', '3.4', '3.5', '9.5', '14.6'] m.fs.b2 = pyo.Block() m.fs.b2.raw_water_withdrawal = pyo.Var(initialize=2902) # gpm m.fs.b2.raw_water_withdrawal.fix() get_PP_costing(m.fs.b2, RW_withdraw_accounts, m.fs.b2.raw_water_withdrawal, 'gpm', 6) # Accounts with fuel gas flowrate as the reference/scaling parameter # Exhibit 5-15 stream 2, Exhibit 5-8 FuelG_accounts = ['3.6', '3.9', '6.1', '6.3', '6.4'] m.fs.b3 = pyo.Block() # Obtain Fuel gas flowrate in acm fuelgas_value = 205630 # lb/hr m.fs.b3.fg_flowrate = pyo.Var(initialize=fuelgas_value) # lb/hr m.fs.b3.fg_flowrate.fix() get_PP_costing(m.fs.b3, FuelG_accounts, m.fs.b3.fg_flowrate, 'lb/hr', 6) # Accounts with process water discharge as the reference/scaling parameter # Exhibit 5-14 PW_discharge_accounts = ['3.7'] m.fs.b4 = pyo.Block() m.fs.b4.process_water_discharge = pyo.Var(initialize=657) # gpm m.fs.b4.process_water_discharge.fix() get_PP_costing(m.fs.b4, PW_discharge_accounts, m.fs.b4.process_water_discharge, 'gpm', 6) # Initialize costing costing_initialization(m.fs) assert degrees_of_freedom(m) == 0 # Solve the model results = solver.solve(m, tee=True) assert pyo.check_optimal_termination(results) # Accounts with raw water withdrawal as reference parameter assert pytest.approx(26.435, abs=0.5) \ == sum(pyo.value(m.fs.b2.costing.total_plant_cost[ac]) for ac in RW_withdraw_accounts) # Accounts with fuel gas as reference parameter assert pytest.approx(158.415, abs=0.5) \ == sum(pyo.value(m.fs.b3.costing.total_plant_cost[ac]) for ac in FuelG_accounts) # Accounts with process water discharge as reference parameter assert pytest.approx(11.608, abs=0.5) \ == sum(pyo.value(m.fs.b4.costing.total_plant_cost[ac]) for ac in PW_discharge_accounts)
def test_costing_distillation_solve(): m = pyo.ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.get_costing() m.fs.costing.CE_index = 550 # create a unit model and variables 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.diameter = pyo.Var(initialize=10, domain=pyo.NonNegativeReals, units=pyo.units.foot) m.fs.unit.length = pyo.Var(initialize=10, domain=pyo.NonNegativeReals, units=pyo.units.foot) # create costing block m.fs.unit.costing = pyo.Block() cs.vessel_costing(m.fs.unit.costing, alignment='vertical', weight_limit='option2', L_D_range='option2', PL=True, plates=True, number_tray=100, ref_parameter_diameter=m.fs.unit.diameter, ref_parameter_length=m.fs.unit.length) # pressure design and shell thickness from Example 22.13 Product and # Process Design Principless m.fs.unit.heat_duty.fix(18390000) # Btu/hr m.fs.unit.pressure.fix(123 + 14.6959) # psia # pressure design minimum thickness tp = 0.582 in # vessel is vertical + quite tall the tower is subject to wind load, # and earthquake. Assume wall thickness of 1.25 in. # The additional wall thickness at the bottom of the tower is 0.889 in # average thickness is 1.027, plus corrosion allowance of 1/8 # 1.152 in, therefore steel plate thickness is 1.250 (ts) m.fs.unit.costing.shell_thickness.set_value(1.250) # inches m.fs.unit.diameter.fix(10) # ft m.fs.unit.length.fix(212) # ft m.fs.unit.costing.number_trays.set_value(100) 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) results = solver.solve(m, tee=False) # Check for optimal solution assert pyo.check_optimal_termination(results) assert (pytest.approx(pyo.value(m.fs.unit.costing.base_cost), abs=1e-2) == 636959.6929) # Example 22.13 Ref Book assert (pytest.approx(pyo.value(m.fs.unit.costing.base_cost_platf_ladders), abs=1e-2) == 97542.9005) # Example 22.13 Ref Book assert (pytest.approx(pyo.value(m.fs.unit.costing.purchase_cost_trays), abs=1e-2) == 293006.086) # Example 22.13 Ref Book assert (pytest.approx(pyo.value(m.fs.unit.costing.purchase_cost), abs=1e-2) == 1100958.9396) # Example 22.13 Ref Book
def test_solve_heat_duty(self, methane): solver.options["tol"] = 1e-9 solver.options["nlp_scaling_method"] = "user-scaling" results = solver.solve(methane, tee=True) # Check for optimal solution assert check_optimal_termination(results)
def test_boiler(boiler): # unfix inlets to build arcs at the flowsheet level boiler.fs.ATMP1.outlet.enth_mol[0].fix(62710.01) boiler.fs.ATMP1.SprayWater.flow_mol[0].unfix() result = boiler.solver.solve(boiler, tee=False) assert check_optimal_termination(result) assert value(boiler.fs.ECON.side_1.properties_out[0].temperature) == \ pytest.approx(521.009, 1)
def test_T376_P1_x2(self, m): m.fs.state[1].flow_mol.fix(100) m.fs.state[1].mole_frac_comp["benzene"].fix(0.2) m.fs.state[1].mole_frac_comp["toluene"].fix(0.8) m.fs.state[1].temperature.fix(376) m.fs.state[1].pressure.fix(1e5) # Trigger build of enthalpy and entropy m.fs.state[1].enth_mol_phase m.fs.state[1].entr_mol_phase m.fs.state.initialize(outlvl=SOUT) results = solver.solve(m) # Check for optimal solution assert check_optimal_termination(results) assert pytest.approx(value(m.fs.state[1]._teq[("Vap", "Liq")]), 1e-5) == 376 assert 0.00361333 == pytest.approx( value(m.fs.state[1].compress_fact_phase["Liq"]), 1e-5) assert 0.968749 == pytest.approx( value(m.fs.state[1].compress_fact_phase["Vap"]), 1e-5) assert pytest.approx( value(m.fs.state[1].fug_coeff_phase_comp["Liq", "benzene"]), 1e-5) == 1.8394188 assert pytest.approx( value(m.fs.state[1].fug_coeff_phase_comp["Liq", "toluene"]), 1e-5) == 0.7871415 assert pytest.approx( value(m.fs.state[1].fug_coeff_phase_comp["Vap", "benzene"]), 1e-5) == 0.9763608 assert pytest.approx( value(m.fs.state[1].fug_coeff_phase_comp["Vap", "toluene"]), 1e-5) == 0.9663611 assert pytest.approx( value(m.fs.state[1].mole_frac_phase_comp["Liq", "benzene"]), 1e-5) == 0.17342 assert pytest.approx( value(m.fs.state[1].mole_frac_phase_comp["Liq", "toluene"]), 1e-5) == 0.82658 assert pytest.approx( value(m.fs.state[1].mole_frac_phase_comp["Vap", "benzene"]), 1e-5) == 0.3267155 assert pytest.approx( value(m.fs.state[1].mole_frac_phase_comp["Vap", "toluene"]), 1e-5) == 0.6732845 assert pytest.approx(value(m.fs.state[1].enth_mol_phase["Liq"]), 1e-5) == 31535.8 assert pytest.approx(value(m.fs.state[1].enth_mol_phase["Vap"]), 1e-5) == 69175.3 assert pytest.approx(value(m.fs.state[1].entr_mol_phase["Liq"]), 1e-5) == -369.033 assert pytest.approx(value(m.fs.state[1].entr_mol_phase["Vap"]), 1e-5) == -273.513
def test_T450_P5_x5(self, m): m.fs.state[1].flow_mol.fix(100) m.fs.state[1].mole_frac_comp["benzene"].fix(0.5) m.fs.state[1].mole_frac_comp["toluene"].fix(0.5) m.fs.state[1].temperature.fix(450) m.fs.state[1].pressure.fix(5e5) # Trigger build of enthalpy and entropy m.fs.state[1].enth_mol_phase m.fs.state[1].entr_mol_phase m.fs.state.initialize(outlvl=SOUT) results = solver.solve(m) # Check for optimal solution assert check_optimal_termination(results) assert pytest.approx(value(m.fs.state[1]._teq[("Vap", "Liq")]), 1e-5) == 436.93 assert 0.0166181 == pytest.approx( value(m.fs.state[1].compress_fact_phase["Liq"]), 1e-5) assert 0.9053766 == pytest.approx( value(m.fs.state[1].compress_fact_phase["Vap"]), 1e-5) assert pytest.approx( value(m.fs.state[1].fug_coeff_phase_comp["Liq", "benzene"]), 1e-5) == 1.63308 assert pytest.approx( value(m.fs.state[1].fug_coeff_phase_comp["Liq", "toluene"]), 1e-5) == 0.873213 assert pytest.approx( value(m.fs.state[1].fug_coeff_phase_comp["Vap", "benzene"]), 1e-5) == 0.927534 assert pytest.approx( value(m.fs.state[1].fug_coeff_phase_comp["Vap", "toluene"]), 1e-5) == 0.898324 assert pytest.approx( value(m.fs.state[1].mole_frac_phase_comp["Liq", "benzene"]), 1e-5) == 0.3488737 assert pytest.approx( value(m.fs.state[1].mole_frac_phase_comp["Liq", "toluene"]), 1e-5) == 0.6511263 assert pytest.approx( value(m.fs.state[1].mole_frac_phase_comp["Vap", "benzene"]), 1e-5) == 0.5 assert pytest.approx( value(m.fs.state[1].mole_frac_phase_comp["Vap", "toluene"]), 1e-5) == 0.5 assert pytest.approx(value(m.fs.state[1].enth_mol_phase["Liq"]), 1e-5) == 51095.2 assert pytest.approx(value(m.fs.state[1].enth_mol_phase["Vap"]), 1e-5) == 83362.3 assert pytest.approx(value(m.fs.state[1].entr_mol_phase["Liq"]), 1e-5) == -326.299 assert pytest.approx(value(m.fs.state[1].entr_mol_phase["Vap"]), 1e-5) == -256.198
def test_T450_P1_x5(self, m): m.fs.state[1].flow_mol.fix(100) m.fs.state[1].mole_frac_comp["benzene"].fix(0.5) m.fs.state[1].mole_frac_comp["toluene"].fix(0.5) m.fs.state[1].temperature.fix(450) m.fs.state[1].pressure.fix(1e5) # Trigger build of enthalpy and entropy m.fs.state[1].enth_mol_phase m.fs.state[1].entr_mol_phase m.fs.state.initialize(outlvl=SOUT) results = solver.solve(m) # Check for optimal solution assert check_optimal_termination(results) assert pytest.approx(value(m.fs.state[1]._teq[("Vap", "Liq")]), 1e-5) == 371.4 assert 0.0033583 == pytest.approx( value(m.fs.state[1].compress_fact_phase["Liq"]), 1e-5) assert 0.9821368 == pytest.approx( value(m.fs.state[1].compress_fact_phase["Vap"]), 1e-5) assert pytest.approx( value(m.fs.state[1].fug_coeff_phase_comp["Liq", "benzene"]), 1e-5) == 8.069323 assert pytest.approx( value(m.fs.state[1].fug_coeff_phase_comp["Liq", "toluene"]), 1e-5) == 4.304955 assert pytest.approx( value(m.fs.state[1].fug_coeff_phase_comp["Vap", "benzene"]), 1e-5) == 0.985365 assert pytest.approx( value(m.fs.state[1].fug_coeff_phase_comp["Vap", "toluene"]), 1e-5) == 0.979457 assert pytest.approx( value(m.fs.state[1].mole_frac_phase_comp["Liq", "benzene"]), 1e-5) == 0.29861 assert pytest.approx( value(m.fs.state[1].mole_frac_phase_comp["Liq", "toluene"]), 1e-5) == 0.70139 assert pytest.approx( value(m.fs.state[1].mole_frac_phase_comp["Vap", "benzene"]), 1e-5) == 0.5 assert pytest.approx( value(m.fs.state[1].mole_frac_phase_comp["Vap", "toluene"]), 1e-5) == 0.5 assert pytest.approx(value(m.fs.state[1].enth_mol_phase["Liq"]), 1e-5) == 49441.2 assert pytest.approx(value(m.fs.state[1].enth_mol_phase["Vap"]), 1e-5) == 84175.1 assert pytest.approx(value(m.fs.state[1].entr_mol_phase["Liq"]), 1e-5) == -328.766 assert pytest.approx(value(m.fs.state[1].entr_mol_phase["Vap"]), 1e-5) == -241.622
def test_T350_P5_x5(self, m): m.fs.state[1].flow_mol.fix(100) m.fs.state[1].mole_frac_comp["benzene"].fix(0.5) m.fs.state[1].mole_frac_comp["toluene"].fix(0.5) m.fs.state[1].temperature.fix(350) m.fs.state[1].pressure.fix(5e5) # Trigger build of enthalpy and entropy m.fs.state[1].enth_mol_phase m.fs.state[1].entr_mol_phase m.fs.state.initialize(outlvl=SOUT) results = solver.solve(m) # Check for optimal solution assert check_optimal_termination(results) assert pytest.approx(value(m.fs.state[1]._teq[("Vap", "Liq")]), 1e-5) == 431.47 assert pytest.approx(value(m.fs.state[1].compress_fact_phase["Liq"]), 1e-5) == 0.01766 assert pytest.approx(value(m.fs.state[1].compress_fact_phase["Vap"]), 1e-5) == 0.80245 assert pytest.approx( value(m.fs.state[1].fug_coeff_phase_comp["Liq", "benzene"]), 1e-5) == 0.181229 assert pytest.approx( value(m.fs.state[1].fug_coeff_phase_comp["Liq", "toluene"]), 1e-5) == 0.070601 assert pytest.approx( value(m.fs.state[1].fug_coeff_phase_comp["Vap", "benzene"]), 1e-5) == 0.856523 assert pytest.approx( value(m.fs.state[1].fug_coeff_phase_comp["Vap", "toluene"]), 1e-5) == 0.799237 assert pytest.approx( value(m.fs.state[1].mole_frac_phase_comp["Liq", "benzene"]), 1e-5) == 0.5 assert pytest.approx( value(m.fs.state[1].mole_frac_phase_comp["Liq", "toluene"]), 1e-5) == 0.5 assert pytest.approx( value(m.fs.state[1].mole_frac_phase_comp["Vap", "benzene"]), 1e-5) == 0.65415 assert pytest.approx( value(m.fs.state[1].mole_frac_phase_comp["Vap", "toluene"]), 1e-5) == 0.34585 assert pytest.approx(value(m.fs.state[1].enth_mol_phase["Liq"]), 1e-5) == 38966.9 assert pytest.approx(value(m.fs.state[1].enth_mol_phase["Vap"]), 1e-5) == 75150.7 assert pytest.approx(value(m.fs.state[1].entr_mol_phase["Liq"]), 1e-5) == -361.8433 assert pytest.approx(value(m.fs.state[1].entr_mol_phase["Vap"]), 1e-5) == -281.9703
def test_T350_P1_x5(self, m): m.fs.state[1].flow_mol.fix(100) m.fs.state[1].mole_frac_comp["benzene"].fix(0.5) m.fs.state[1].mole_frac_comp["toluene"].fix(0.5) m.fs.state[1].temperature.fix(350) m.fs.state[1].pressure.fix(1e5) # Trigger build of enthalpy and entropy m.fs.state[1].enth_mol_phase m.fs.state[1].entr_mol_phase m.fs.state.initialize(outlvl=SOUT) results = solver.solve(m) # Check for optimal solution assert check_optimal_termination(results) assert pytest.approx(value(m.fs.state[1]._teq[("Vap", "Liq")]), abs=1e-1) == 365 assert 0.0035346 == pytest.approx( value(m.fs.state[1].compress_fact_phase["Liq"]), 1e-5) assert 0.966749 == pytest.approx( value(m.fs.state[1].compress_fact_phase["Vap"]), 1e-5) assert pytest.approx( value(m.fs.state[1].fug_coeff_phase_comp["Liq", "benzene"]), 1e-5) == 0.894676 assert pytest.approx( value(m.fs.state[1].fug_coeff_phase_comp["Liq", "toluene"]), 1e-5) == 0.347566 assert pytest.approx( value(m.fs.state[1].fug_coeff_phase_comp["Vap", "benzene"]), 1e-5) == 0.971072 assert pytest.approx( value(m.fs.state[1].fug_coeff_phase_comp["Vap", "toluene"]), 1e-5) == 0.959791 assert pytest.approx( value(m.fs.state[1].mole_frac_phase_comp["Liq", "benzene"]), 1e-5) == 0.5 assert pytest.approx( value(m.fs.state[1].mole_frac_phase_comp["Liq", "toluene"]), 1e-5) == 0.5 assert pytest.approx( value(m.fs.state[1].mole_frac_phase_comp["Vap", "benzene"]), 1e-5) == 0.70584 assert pytest.approx( value(m.fs.state[1].mole_frac_phase_comp["Vap", "toluene"]), 1e-5) == 0.29416 assert pytest.approx(value(m.fs.state[1].enth_mol_phase["Liq"]), 1e-5) == 38942.8 assert pytest.approx(value(m.fs.state[1].enth_mol_phase["Vap"]), 1e-5) == 78048.7 assert pytest.approx(value(m.fs.state[1].entr_mol_phase["Liq"]), 1e-5) == -361.794 assert pytest.approx(value(m.fs.state[1].entr_mol_phase["Vap"]), 1e-5) == -264.0181