From 435990b7a6009931a66be3ec6c7aacb66566445d Mon Sep 17 00:00:00 2001 From: Mukta Hardikar Date: Fri, 22 Nov 2024 08:35:43 -0700 Subject: [PATCH] updates to run sweeps for hours storage and set electricity price --- .../case_studies/KBHDP/KBHDP_RPT_3.py | 86 ++++++++++++------- .../case_studies/KBHDP/RPT3_sweeps.py | 30 ------- .../case_studies/KBHDP/components/FPC.py | 85 +++++++++++++++--- .../case_studies/KBHDP/components/MD.py | 24 +++--- 4 files changed, 137 insertions(+), 88 deletions(-) delete mode 100644 src/watertap_contrib/reflo/analysis/case_studies/KBHDP/RPT3_sweeps.py diff --git a/src/watertap_contrib/reflo/analysis/case_studies/KBHDP/KBHDP_RPT_3.py b/src/watertap_contrib/reflo/analysis/case_studies/KBHDP/KBHDP_RPT_3.py index fe6b1ddd..1e13b914 100644 --- a/src/watertap_contrib/reflo/analysis/case_studies/KBHDP/KBHDP_RPT_3.py +++ b/src/watertap_contrib/reflo/analysis/case_studies/KBHDP/KBHDP_RPT_3.py @@ -172,13 +172,15 @@ def add_costing(m, treatment_costing_block, energy_costing_block): add_DWI_costing(m.fs.treatment, m.fs.treatment.dwi, treatment_costing_block) -def calc_costing(m): +def calc_costing(m,heat_price=0.01, electricity_price = 0.07): # Touching variables to solve for volumetric flow rate m.fs.product.properties[0].flow_vol_phase # Treatment costing # m.fs.treatment.costing.capital_recovery_factor.fix(0.08764) # m.fs.treatment.costing.wacc.unfix() + m.fs.treatment.costing.heat_cost.fix(heat_price) + m.fs.treatment.costing.electricity_cost.fix(electricity_price) m.fs.treatment.costing.cost_process() m.fs.treatment.costing.initialize() @@ -189,23 +191,27 @@ def calc_costing(m): m.fs.treatment.costing.add_LCOW(m.fs.product.properties[0].flow_vol) # Energy costing + m.fs.energy.costing.electricity_cost.fix(electricity_price) m.fs.energy.costing.cost_process() m.fs.energy.costing.initialize() m.fs.energy.costing.add_annual_water_production(m.fs.product.properties[0].flow_vol) - m.fs.energy.costing.add_LCOW(m.fs.product.properties[0].flow_vol) + m.fs.energy.costing.add_LCOH() -def add_system_costing(m, heat_price=0.01, frac_heat_from_grid=0.01): +def add_system_costing(m, heat_price=0.01, electricity_price = 0.07, frac_heat_from_grid=0.01): # System costing m.fs.sys_costing = REFLOSystemCosting() m.fs.sys_costing.frac_heat_from_grid.fix(frac_heat_from_grid) m.fs.sys_costing.heat_cost_buy.set_value(heat_price) + m.fs.sys_costing.electricity_cost_buy.set_value(electricity_price) m.fs.sys_costing.cost_process() + print("\n--------- INITIALIZING SYSTEM COSTING ---------\n") m.fs.sys_costing.initialize() m.fs.sys_costing.add_annual_water_production(m.fs.product.properties[0].flow_vol) - m.fs.sys_costing.add_LCOW(m.fs.product.properties[0].flow_vol) + m.fs.sys_costing.add_LCOT(m.fs.product.properties[0].flow_vol) + m.fs.sys_costing.add_LCOH() def set_inlet_conditions(blk, model_options): @@ -229,10 +235,10 @@ def set_inlet_conditions(blk, model_options): ) -def set_operating_conditions(m): +def set_operating_conditions(m,hours_storage=8): set_md_op_conditions(m.fs.treatment.md) - set_fpc_op_conditions(m.fs.energy.fpc, hours_storage=8, temperature_hot=80) + set_fpc_op_conditions(m.fs.energy.fpc, hours_storage=hours_storage, temperature_hot=80) def init_system(m, blk, model_options, n_time_points, verbose=True, solver=None): @@ -287,7 +293,7 @@ def solve(m, solver=None, tee=True, raise_on_failure=True): def optimize(m): m.fs.sys_costing.frac_heat_from_grid.unfix() - m.fs.obj = Objective(expr=m.fs.sys_costing.LCOW) + m.fs.obj = Objective(expr=(m.fs.sys_costing.LCOT)) def report_sys_costing(blk): @@ -295,7 +301,7 @@ def report_sys_costing(blk): print(f"\n\n-------------------- System Costing Report --------------------\n") print("\n") - print(f'{"LCOW":<30s}{value(blk.LCOW):<20,.2f}{pyunits.get_units(blk.LCOW)}') + print(f'{"LCOT":<30s}{value(blk.LCOT):<20,.2f}{pyunits.get_units(blk.LCOT)}') print( f'{"Capital Cost":<30s}{value(blk.total_capital_cost):<20,.2f}{pyunits.get_units(blk.total_capital_cost)}' @@ -362,7 +368,7 @@ def set_inlet_stream_conditions(Qinput=4, feed_salinity_input=12, water_recovery return inlet_cond -def main(water_recovery=0.5, heat_price=0.07, frac_heat_from_grid=0.01): +def main(water_recovery=0.5, heat_price=0.07, electricity_price = 0.07,frac_heat_from_grid=0.01,hours_storage = 8): solver = get_solver() solver = SolverFactory("ipopt") @@ -381,7 +387,7 @@ def main(water_recovery=0.5, heat_price=0.07, frac_heat_from_grid=0.01): init_system(m, m.fs, model_options, n_time_points) - set_operating_conditions(m) + set_operating_conditions(m,hours_storage) print(f"\nBefore Costing System Degrees of Freedom: {degrees_of_freedom(m)}") @@ -393,8 +399,8 @@ def main(water_recovery=0.5, heat_price=0.07, frac_heat_from_grid=0.01): energy_costing_block=m.fs.energy.costing, ) - calc_costing(m) - add_system_costing(m, heat_price, frac_heat_from_grid) + calc_costing(m,heat_price, electricity_price) + add_system_costing(m, heat_price,electricity_price, frac_heat_from_grid) # add_energy_constraints(m) @@ -407,6 +413,8 @@ def main(water_recovery=0.5, heat_price=0.07, frac_heat_from_grid=0.01): print(f"\nAfter Solve System Degrees of Freedom: {degrees_of_freedom(m)}") + print_results_summary(m) + optimize(m) solve(m, solver=solver, tee=False) @@ -424,12 +432,12 @@ def print_results_summary(m): print("\n") print( - f'{"Energy LCOW":<30s}{value(m.fs.energy.costing.LCOW):<10.2f}{pyunits.get_units(m.fs.energy.costing.LCOW)}' + f'{"Energy LCOH":<30s}{value(m.fs.energy.costing.LCOH):<10.2f}{pyunits.get_units(m.fs.energy.costing.LCOH)}' ) print("\n") print( - f'{"System LCOW":<30s}{value(m.fs.sys_costing.LCOW):<10.2f}{pyunits.get_units(m.fs.sys_costing.LCOW)}' + f'{"System LCOT":<30s}{value(m.fs.sys_costing.LCOT) :<10.2f}{pyunits.get_units(m.fs.sys_costing.LCOT)}' ) print("\n") @@ -447,12 +455,14 @@ def print_results_summary(m): report_sys_costing(m.fs.sys_costing) -def save_results(m, sweep_type=None): +def save_results(m): results_df = pd.DataFrame( columns=[ "water_recovery", "heat_price", + "LCOH", + "hours_storage", "frac_heat_from_grid", "product_annual_production", "utilization_factor", @@ -479,8 +489,8 @@ def save_results(m, sweep_type=None): } fixed_opex_output = { - "FPC": value(m.fs.energy.fpc.unit.costing.fixed_operating_cost) - + value(m.fs.energy.fpc.unit.costing.capital_cost) + "FPC": value(m.fs.energy.fpc.unit.costing.fixed_operating_cost)\ + + value(m.fs.energy.fpc.unit.costing.capital_cost)\ * value(m.fs.energy.costing.maintenance_labor_chemical_factor), "MD": value( m.fs.treatment.md.unit.get_active_process_blocks()[ @@ -507,9 +517,11 @@ def save_results(m, sweep_type=None): for unit in ["FPC", "MD", "DWI", "Heat", "Electricity"]: # Add fixed_opex - temp = plot_results = { + temp = { "water_recovery": value(m.fs.water_recovery), "heat_price": value(m.fs.sys_costing.heat_cost_buy), + "LCOH": value(m.fs.energy.costing.LCOH), + "hours_storage": value(m.fs.energy.fpc.unit.hours_storage), "frac_heat_from_grid": value(m.fs.sys_costing.frac_heat_from_grid), "product_annual_production": value( m.fs.sys_costing.annual_water_production @@ -522,9 +534,11 @@ def save_results(m, sweep_type=None): } results_df = results_df.append(temp, ignore_index=True) # Add variable opex - temp = plot_results = { + temp = { "water_recovery": value(m.fs.water_recovery), "heat_price": value(m.fs.sys_costing.heat_cost_buy), + "LCOH": value(m.fs.energy.costing.LCOH), + "hours_storage": value(m.fs.energy.fpc.unit.hours_storage), "frac_heat_from_grid": value(m.fs.sys_costing.frac_heat_from_grid), "product_annual_production": value( m.fs.sys_costing.annual_water_production @@ -538,9 +552,11 @@ def save_results(m, sweep_type=None): results_df = results_df.append(temp, ignore_index=True) # Add opex - temp = plot_results = { + temp = { "water_recovery": value(m.fs.water_recovery), "heat_price": value(m.fs.sys_costing.heat_cost_buy), + "LCOH": value(m.fs.energy.costing.LCOH), + "hours_storage": value(m.fs.energy.fpc.unit.hours_storage), "frac_heat_from_grid": value(m.fs.sys_costing.frac_heat_from_grid), "product_annual_production": value( m.fs.sys_costing.annual_water_production @@ -554,9 +570,11 @@ def save_results(m, sweep_type=None): results_df = results_df.append(temp, ignore_index=True) # Add capex - temp = plot_results = { + temp = { "water_recovery": value(m.fs.water_recovery), "heat_price": value(m.fs.sys_costing.heat_cost_buy), + "LCOH": value(m.fs.energy.costing.LCOH), + "hours_storage": value(m.fs.energy.fpc.unit.hours_storage), "frac_heat_from_grid": value(m.fs.sys_costing.frac_heat_from_grid), "product_annual_production": value( m.fs.sys_costing.annual_water_production @@ -580,18 +598,11 @@ def save_results(m, sweep_type=None): + str(value(m.fs.water_recovery)) + "_heat_price_" + str(value(m.fs.sys_costing.heat_cost_buy)) + + "_hours_storage_" + + str(value(m.fs.energy.fpc.unit.hours_storage)) ) - if sweep_type != None: - results_df.to_csv( - r"C:\Users\mhardika\Documents\SETO\Case Studies\RPT3\RPT3_results\\" - + sweep_type - + "\\" - + file_name - + ".csv" - ) - else: - results_df.to_csv( + results_df.to_csv( r"C:\Users\mhardika\Documents\SETO\Case Studies\RPT3\RPT3_results\\" + file_name + ".csv" @@ -601,7 +612,16 @@ def save_results(m, sweep_type=None): if __name__ == "__main__": - m = main(water_recovery=0.8, heat_price=0.08, frac_heat_from_grid=0.01) + m = main(water_recovery=0.5, + heat_price=0.08, + electricity_price = 0.07, + frac_heat_from_grid=0.05, + hours_storage = 6) - save_results(m) + # save_results(m) print_results_summary(m) + + # print(m.fs.sys_costing.treat_operating_cost_no_energy()) + # print(m.fs.sys_costing.energy_operating_cost_no_energy()) + # print(m.fs.sys_costing.total_heat_operating_cost()) + # print(m.fs.sys_costing.total_electric_operating_cost()) \ No newline at end of file diff --git a/src/watertap_contrib/reflo/analysis/case_studies/KBHDP/RPT3_sweeps.py b/src/watertap_contrib/reflo/analysis/case_studies/KBHDP/RPT3_sweeps.py deleted file mode 100644 index 83da2b82..00000000 --- a/src/watertap_contrib/reflo/analysis/case_studies/KBHDP/RPT3_sweeps.py +++ /dev/null @@ -1,30 +0,0 @@ -from idaes.core.solvers import get_solver -from pyomo.environ import SolverFactory -from watertap_contrib.reflo.analysis.case_studies.KBHDP.KBHDP_RPT_3 import ( - main, - save_results, -) - - -def sweep(sweep_type, water_recovery=0.5, heat_price=0.07, frac_heat_from_grid=0.01): - m = main( - water_recovery=water_recovery, - heat_price=heat_price, - frac_heat_from_grid=frac_heat_from_grid, - ) - save_results(m, sweep_type=sweep_type) - - -if __name__ == "__main__": - water_recovery_sweep = [0.2, 0.3, 0.4, 0.5, 0.6, 0.7] - heat_price_sweep = [0.07, 0.075, 0.08, 0.085, 0.09, 0.095, 0.1] - for recovery in water_recovery_sweep: - sweep( - "water_recovery_1", - water_recovery=recovery, - heat_price=0.08, - frac_heat_from_grid=0.01, - ) - - # for heat_price in heat_price_sweep: - # sweep('heat_price_1',water_recovery=0.5,heat_price = heat_price,frac_heat_from_grid=0.01) diff --git a/src/watertap_contrib/reflo/analysis/case_studies/KBHDP/components/FPC.py b/src/watertap_contrib/reflo/analysis/case_studies/KBHDP/components/FPC.py index 9984f65d..6be7bd5c 100644 --- a/src/watertap_contrib/reflo/analysis/case_studies/KBHDP/components/FPC.py +++ b/src/watertap_contrib/reflo/analysis/case_studies/KBHDP/components/FPC.py @@ -6,6 +6,7 @@ Block, Constraint, SolverFactory, + check_optimal_termination, ) import os @@ -18,6 +19,7 @@ from watertap_contrib.reflo.solar_models.surrogate.flat_plate.flat_plate_surrogate import ( FlatPlateSurrogate, ) +from idaes.core.util.model_statistics import * from idaes.core.util.model_statistics import ( degrees_of_freedom, @@ -30,6 +32,8 @@ EnergyCosting, ) +import idaes.core.util.scaling as iscale + __all__ = [ "build_fpc", "init_fpc", @@ -102,6 +106,10 @@ def init_fpc(blk): def set_system_op_conditions(m): m.fs.system_capacity.fix() +def add_fpc_scaling(m,blk): + iscale.set_scaling_factor(blk.unit.hours_storage, 10) + iscale.set_scaling_factor(blk.unit.electricity, 100) + iscale.set_scaling_factor(blk.unit.heat_load, 1e4) def set_fpc_op_conditions(blk, hours_storage=6, temperature_hot=80): @@ -118,12 +126,49 @@ def add_fpc_costing(blk, costing_block): def calc_costing(m, blk): blk.costing.heat_cost.set_value(0) + blk.costing.electricity_cost.fix(0.07) blk.costing.cost_process() blk.costing.initialize() # TODO: Connect to the treatment volume - blk.costing.add_LCOW(m.fs.system_capacity) + blk.costing.add_LCOH() + + +def solve(m, solver=None, tee=False, raise_on_failure=True, debug=False): + # ---solving--- + if solver is None: + solver = get_solver() + solver.options["max_iter"] = 2000 + print("\n--------- SOLVING ---------\n") + + results = solver.solve(m, tee=tee) + + if check_optimal_termination(results): + print("\n--------- OPTIMAL SOLVE!!! ---------\n") + if debug: + print("\n--------- CHECKING JACOBIAN ---------\n") + # check_jac(m) + + print("\n--------- CLOSE TO BOUNDS ---------\n") + print_close_to_bounds(m) + return results + msg = ( + "The current configuration is infeasible. Please adjust the decision variables." + ) + if raise_on_failure: + print('\n{"=======> INFEASIBLE BOUNDS <=======":^60}\n') + print_infeasible_bounds(m) + print('\n{"=======> INFEASIBLE CONSTRAINTS <=======":^60}\n') + print_infeasible_constraints(m) + print('\n{"=======> CLOSE TO BOUNDS <=======":^60}\n') + print_close_to_bounds(m) + + raise RuntimeError(msg) + else: + print("\n--------- FAILED SOLVE!!! ---------\n") + print(msg) + assert False def report_fpc(m, blk): # blk = m.fs.fpc @@ -142,6 +187,10 @@ def report_fpc(m, blk): f'{"Storage volume":<30s}{value(blk.storage_volume):<20,.2f}{pyunits.get_units(blk.storage_volume)}' ) + print( + f'{"Hours of storage":<30s}{value(blk.hours_storage):<20,.2f}{pyunits.get_units(blk.hours_storage)}' + ) + print( f'{"Heat load":<30s}{value(blk.heat_load):<20,.2f}{pyunits.get_units(blk.heat_load)}' ) @@ -166,7 +215,7 @@ def report_fpc_costing(m, blk): print("\n") print( - f'{"LCOW":<30s}{value(blk.costing.LCOW):<20,.2f}{pyunits.get_units(blk.costing.LCOW)}' + f'{"LCOH":<30s}{value(blk.costing.LCOH):<20,.2f}{pyunits.get_units(blk.costing.LCOH)}' ) print( @@ -174,12 +223,12 @@ def report_fpc_costing(m, blk): ) print( - f'{"Fixed Operating Cost":<30s}{value(blk.costing.total_fixed_operating_cost):<20,.2f}{pyunits.get_units(blk.costing.total_fixed_operating_cost)}' + f'{"Fixed Operating Cost":<30s}{value(blk.fpc.unit.costing.fixed_operating_cost):<20,.2f}{pyunits.get_units(blk.costing.total_fixed_operating_cost)}' ) - print( - f'{"Variable Operating Cost":<30s}{value(blk.costing.total_variable_operating_cost):<20,.2f}{pyunits.get_units(blk.costing.total_variable_operating_cost)}' - ) + # print( + # f'{"Variable Operating Cost":<30s}{value(blk.costing.variable_operating_cost):<20,.2f}{pyunits.get_units(blk.costing.total_variable_operating_cost)}' + # ) print( f'{"Total Operating Cost":<30s}{value(blk.costing.total_operating_cost):<20,.2f}{pyunits.get_units(blk.costing.total_operating_cost)}' @@ -205,8 +254,7 @@ def report_fpc_costing(m, blk): # f'{"Elec Cost":<30s}{value(blk.costing.aggregate_flow_costs["electricity"]):<20,.2f}{pyunits.get_units(blk.costing.aggregate_flow_costs["electricity"])}' # ) - -if __name__ == "__main__": +def main(): solver = get_solver() solver = SolverFactory("ipopt") @@ -215,17 +263,28 @@ def report_fpc_costing(m, blk): build_fpc(m.fs.fpc) init_fpc(m.fs.fpc) - set_fpc_op_conditions(m.fs.fpc) - + set_fpc_op_conditions(m.fs.fpc, hours_storage=6) + add_fpc_scaling(m, m.fs.fpc) print("Degrees of Freedom:", degrees_of_freedom(m)) add_fpc_costing(m.fs.fpc, costing_block=m.fs.costing) calc_costing(m, m.fs) - m.fs.costing.aggregate_flow_heat.fix(-4000) - results = solver.solve(m) + m.fs.costing.aggregate_flow_heat.fix(-7842) + print("\nDegrees of Freedom after fixing aggregate heat flow:", degrees_of_freedom(m)) + # results = solver.solve(m) + solve(m, solver=solver, tee=False) + return m + +if __name__ == "__main__": + + + m = main() + print(degrees_of_freedom(m)) report_fpc(m, m.fs.fpc.unit) report_fpc_costing(m, m.fs) + + # m.fs.fpc.unit.costing.display() + - # m.fs.costing.used_flows.display() diff --git a/src/watertap_contrib/reflo/analysis/case_studies/KBHDP/components/MD.py b/src/watertap_contrib/reflo/analysis/case_studies/KBHDP/components/MD.py index d5cb3299..e9170593 100644 --- a/src/watertap_contrib/reflo/analysis/case_studies/KBHDP/components/MD.py +++ b/src/watertap_contrib/reflo/analysis/case_studies/KBHDP/components/MD.py @@ -670,21 +670,21 @@ def report_md_costing(m, blk): f'{"Membrane Cost":<30s}{value(active_blks[-1].fs.vagmd.costing.module_cost):<20,.2f}{pyunits.get_units(active_blks[-1].fs.vagmd.costing.module_cost)}' ) - print( - f'{"Heat flow":<30s}{value(blk.costing.aggregate_flow_heat):<20,.2f}{pyunits.get_units(blk.costing.aggregate_flow_heat)}' - ) + # print( + # f'{"Heat flow":<30s}{value(blk.costing.aggregate_flow_heat):<20,.2f}{pyunits.get_units(blk.costing.aggregate_flow_heat)}' + # ) - print( - f'{"Aggregated Heat Cost":<30s}{value(blk.costing.aggregate_flow_costs["heat"]):<20,.2f}{pyunits.get_units(blk.costing.aggregate_flow_costs["heat"])}' - ) + # print( + # f'{"Aggregated Heat Cost":<30s}{value(blk.costing.aggregate_flow_costs["heat"]):<20,.2f}{pyunits.get_units(blk.costing.aggregate_flow_costs["heat"])}' + # ) - print( - f'{"Elec Flow":<30s}{value(blk.costing.aggregate_flow_electricity):<20,.2f}{pyunits.get_units(blk.costing.aggregate_flow_electricity)}' - ) + # print( + # f'{"Elec Flow":<30s}{value(blk.costing.aggregate_flow_electricity):<20,.2f}{pyunits.get_units(blk.costing.aggregate_flow_electricity)}' + # ) - print( - f'{"Aggregated Elec Cost":<30s}{value(blk.costing.aggregate_flow_costs["electricity"]):<20,.2f}{pyunits.get_units(blk.costing.aggregate_flow_costs["electricity"])}' - ) + # print( + # f'{"Aggregated Elec Cost":<30s}{value(blk.costing.aggregate_flow_costs["electricity"]):<20,.2f}{pyunits.get_units(blk.costing.aggregate_flow_costs["electricity"])}' + # ) if __name__ == "__main__":