diff --git a/watertap/flowsheets/full_water_resource_recovery_facility/BSM2_P_extension.py b/watertap/flowsheets/full_water_resource_recovery_facility/BSM2_P_extension.py index 136d9aeea5..69544df8d3 100644 --- a/watertap/flowsheets/full_water_resource_recovery_facility/BSM2_P_extension.py +++ b/watertap/flowsheets/full_water_resource_recovery_facility/BSM2_P_extension.py @@ -25,7 +25,8 @@ from idaes.core import ( FlowsheetBlock, - # UnitModelCostingBlock, + UnitModelCostingBlock, + UnitModelBlockData, ) from idaes.models.unit_models import ( CSTR, @@ -78,14 +79,15 @@ from watertap.core.util.initialization import ( check_solve, - # assert_degrees_of_freedom + assert_degrees_of_freedom, + interval_initializer, ) -# from watertap.costing import WaterTAPCosting -# from watertap.costing.unit_models.clarifier import ( -# cost_circular_clarifier, -# cost_primary_clarifier, -# ) +from watertap.costing import WaterTAPCosting +from watertap.costing.unit_models.clarifier import ( + cost_circular_clarifier, + cost_primary_clarifier, +) # Set up logger _log = idaeslog.getLogger(__name__) @@ -129,16 +131,18 @@ def main(bio_P=False): fail_flag=True, ) - # add_costing(m) - # m.fs.costing.initialize() - # - # assert_degrees_of_freedom(m, 0) - # - # results = solve(m) - # pyo.assert_optimal_termination(results) - # - # display_costing(m) - # display_performance_metrics(m) + add_costing(m) + m.fs.costing.initialize() + + interval_initializer(m.fs.costing) + + assert_degrees_of_freedom(m, 0) + + results = solve(m) + pyo.assert_optimal_termination(results) + + display_costing(m) + display_performance_metrics(m) return m, results @@ -689,184 +693,184 @@ def solve(m, solver=None): return results -# def add_costing(m): -# m.fs.costing = WaterTAPCosting() -# m.fs.costing.base_currency = pyo.units.USD_2020 -# -# # Costing Blocks -# m.fs.R1.costing = UnitModelCostingBlock(flowsheet_costing_block=m.fs.costing) -# m.fs.R2.costing = UnitModelCostingBlock(flowsheet_costing_block=m.fs.costing) -# m.fs.R3.costing = UnitModelCostingBlock(flowsheet_costing_block=m.fs.costing) -# m.fs.R4.costing = UnitModelCostingBlock(flowsheet_costing_block=m.fs.costing) -# m.fs.R5.costing = UnitModelCostingBlock(flowsheet_costing_block=m.fs.costing) -# m.fs.R6.costing = UnitModelCostingBlock(flowsheet_costing_block=m.fs.costing) -# m.fs.R7.costing = UnitModelCostingBlock(flowsheet_costing_block=m.fs.costing) -# m.fs.CL.costing = UnitModelCostingBlock( -# flowsheet_costing_block=m.fs.costing, -# costing_method=cost_primary_clarifier, -# ) -# -# m.fs.CL2.costing = UnitModelCostingBlock( -# flowsheet_costing_block=m.fs.costing, -# costing_method=cost_circular_clarifier, -# ) -# -# m.fs.AD.costing = UnitModelCostingBlock(flowsheet_costing_block=m.fs.costing) -# m.fs.dewater.costing = UnitModelCostingBlock(flowsheet_costing_block=m.fs.costing) -# m.fs.thickener.costing = UnitModelCostingBlock(flowsheet_costing_block=m.fs.costing) -# -# # TODO: Leaving out mixer costs; consider including later -# -# # process costing and add system level metrics -# m.fs.costing.cost_process() -# m.fs.costing.add_annual_water_production(m.fs.Treated.properties[0].flow_vol) -# m.fs.costing.add_LCOW(m.fs.FeedWater.properties[0].flow_vol) -# m.fs.costing.add_specific_energy_consumption(m.fs.FeedWater.properties[0].flow_vol) -# -# m.fs.objective = pyo.Objective(expr=m.fs.costing.LCOW) -# iscale.set_scaling_factor(m.fs.costing.LCOW, 1e3) -# iscale.set_scaling_factor(m.fs.costing.total_capital_cost, 1e-7) -# iscale.set_scaling_factor(m.fs.costing.total_operating_cost, 1e-5) -# -# iscale.calculate_scaling_factors(m.fs) +def add_costing(m): + m.fs.costing = WaterTAPCosting() + m.fs.costing.base_currency = pyo.units.USD_2020 + # Costing Blocks + m.fs.R1.costing = UnitModelCostingBlock(flowsheet_costing_block=m.fs.costing) + m.fs.R2.costing = UnitModelCostingBlock(flowsheet_costing_block=m.fs.costing) + m.fs.R3.costing = UnitModelCostingBlock(flowsheet_costing_block=m.fs.costing) + m.fs.R4.costing = UnitModelCostingBlock(flowsheet_costing_block=m.fs.costing) + m.fs.R5.costing = UnitModelCostingBlock(flowsheet_costing_block=m.fs.costing) + m.fs.R6.costing = UnitModelCostingBlock(flowsheet_costing_block=m.fs.costing) + m.fs.R7.costing = UnitModelCostingBlock(flowsheet_costing_block=m.fs.costing) + m.fs.CL.costing = UnitModelCostingBlock( + flowsheet_costing_block=m.fs.costing, + costing_method=cost_primary_clarifier, + ) -# def display_costing(m): -# print("Levelized cost of water: %.2f $/m3" % pyo.value(m.fs.costing.LCOW)) -# -# print( -# "Total operating cost: %.2f $/yr" % pyo.value(m.fs.costing.total_operating_cost) -# ) -# print("Total capital cost: %.2f $" % pyo.value(m.fs.costing.total_capital_cost)) -# -# print( -# "Total annualized cost: %.2f $/yr" -# % pyo.value(m.fs.costing.total_annualized_cost) -# ) -# -# print( -# "capital cost R1", -# pyo.value(m.fs.R1.costing.capital_cost), -# pyo.units.get_units(m.fs.R1.costing.capital_cost), -# ) -# print( -# "capital cost R2", -# pyo.value(m.fs.R2.costing.capital_cost), -# pyo.units.get_units(m.fs.R2.costing.capital_cost), -# ) -# print( -# "capital cost R3", -# pyo.value(m.fs.R3.costing.capital_cost), -# pyo.units.get_units(m.fs.R3.costing.capital_cost), -# ) -# print( -# "capital cost R4", -# pyo.value(m.fs.R4.costing.capital_cost), -# pyo.units.get_units(m.fs.R4.costing.capital_cost), -# ) -# print( -# "capital cost R5", -# pyo.value(m.fs.R5.costing.capital_cost), -# pyo.units.get_units(m.fs.R5.costing.capital_cost), -# ) -# print( -# "capital cost R6", -# pyo.value(m.fs.R6.costing.capital_cost), -# pyo.units.get_units(m.fs.R6.costing.capital_cost), -# ) -# print( -# "capital cost R7", -# pyo.value(m.fs.R7.costing.capital_cost), -# pyo.units.get_units(m.fs.R7.costing.capital_cost), -# ) -# print( -# "capital cost primary clarifier", -# pyo.value(m.fs.CL.costing.capital_cost), -# pyo.units.get_units(m.fs.CL.costing.capital_cost), -# ) -# print( -# "capital cost secondary clarifier", -# pyo.value(m.fs.CL2.costing.capital_cost), -# pyo.units.get_units(m.fs.CL2.costing.capital_cost), -# ) -# print( -# "capital cost AD", -# pyo.value(m.fs.AD.costing.capital_cost), -# pyo.units.get_units(m.fs.AD.costing.capital_cost), -# ) -# print( -# "capital cost dewatering Unit", -# pyo.value(m.fs.dewater.costing.capital_cost), -# pyo.units.get_units(m.fs.dewater.costing.capital_cost), -# ) -# print( -# "capital cost thickener unit", -# pyo.value(m.fs.thickener.costing.capital_cost), -# pyo.units.get_units(m.fs.thickener.costing.capital_cost), -# ) -# -# -# def display_performance_metrics(m): -# print( -# "Specific energy consumption with respect to influent flowrate: %.1f kWh/m3" -# % pyo.value(m.fs.costing.specific_energy_consumption) -# ) -# -# print( -# "electricity consumption R5", -# pyo.value(m.fs.R5.electricity_consumption[0]), -# pyo.units.get_units(m.fs.R5.electricity_consumption[0]), -# ) -# print( -# "electricity consumption R6", -# pyo.value(m.fs.R6.electricity_consumption[0]), -# pyo.units.get_units(m.fs.R6.electricity_consumption[0]), -# ) -# print( -# "electricity consumption R7", -# pyo.value(m.fs.R7.electricity_consumption[0]), -# pyo.units.get_units(m.fs.R7.electricity_consumption[0]), -# ) -# print( -# "electricity consumption primary clarifier", -# pyo.value(m.fs.CL.electricity_consumption[0]), -# pyo.units.get_units(m.fs.CL.electricity_consumption[0]), -# ) -# print( -# "electricity consumption secondary clarifier", -# pyo.value(m.fs.CL2.electricity_consumption[0]), -# pyo.units.get_units(m.fs.CL2.electricity_consumption[0]), -# ) -# print( -# "electricity consumption AD", -# pyo.value(m.fs.AD.electricity_consumption[0]), -# pyo.units.get_units(m.fs.AD.electricity_consumption[0]), -# ) -# print( -# "electricity consumption dewatering Unit", -# pyo.value(m.fs.dewater.electricity_consumption[0]), -# pyo.units.get_units(m.fs.dewater.electricity_consumption[0]), -# ) -# print( -# "electricity consumption thickening Unit", -# pyo.value(m.fs.thickener.electricity_consumption[0]), -# pyo.units.get_units(m.fs.thickener.electricity_consumption[0]), -# ) -# print( -# "Influent flow", -# pyo.value(m.fs.FeedWater.flow_vol[0]), -# pyo.units.get_units(m.fs.FeedWater.flow_vol[0]), -# ) -# print( -# "flow into R3", -# pyo.value(m.fs.R3.control_volume.properties_in[0].flow_vol), -# pyo.units.get_units(m.fs.R3.control_volume.properties_in[0].flow_vol), -# ) -# print( -# "flow into RADM", -# pyo.value(m.fs.AD.liquid_phase.properties_in[0].flow_vol), -# pyo.units.get_units(m.fs.AD.liquid_phase.properties_in[0].flow_vol), -# ) + m.fs.CL2.costing = UnitModelCostingBlock( + flowsheet_costing_block=m.fs.costing, + costing_method=cost_circular_clarifier, + ) + + m.fs.AD.costing = UnitModelCostingBlock(flowsheet_costing_block=m.fs.costing) + m.fs.dewater.costing = UnitModelCostingBlock(flowsheet_costing_block=m.fs.costing) + m.fs.thickener.costing = UnitModelCostingBlock(flowsheet_costing_block=m.fs.costing) + + # TODO: Leaving out mixer costs; consider including later + + # process costing and add system level metrics + m.fs.costing.cost_process() + m.fs.costing.add_annual_water_production(m.fs.Treated.properties[0].flow_vol) + m.fs.costing.add_LCOW(m.fs.FeedWater.properties[0].flow_vol) + m.fs.costing.add_specific_energy_consumption(m.fs.FeedWater.properties[0].flow_vol) + + m.fs.objective = pyo.Objective(expr=m.fs.costing.LCOW) + iscale.set_scaling_factor(m.fs.costing.total_capital_cost, 1e-5) + + for block in m.fs.component_objects(pyo.Block, descend_into=True): + if isinstance(block, UnitModelBlockData) and hasattr(block, "costing"): + iscale.set_scaling_factor(block.costing.capital_cost, 1e-5) + + +def display_costing(m): + print("Levelized cost of water: %.2f $/m3" % pyo.value(m.fs.costing.LCOW)) + + print( + "Total operating cost: %.2f $/yr" % pyo.value(m.fs.costing.total_operating_cost) + ) + print("Total capital cost: %.2f $" % pyo.value(m.fs.costing.total_capital_cost)) + + print( + "Total annualized cost: %.2f $/yr" + % pyo.value(m.fs.costing.total_annualized_cost) + ) + + print( + "capital cost R1", + pyo.value(m.fs.R1.costing.capital_cost), + pyo.units.get_units(m.fs.R1.costing.capital_cost), + ) + print( + "capital cost R2", + pyo.value(m.fs.R2.costing.capital_cost), + pyo.units.get_units(m.fs.R2.costing.capital_cost), + ) + print( + "capital cost R3", + pyo.value(m.fs.R3.costing.capital_cost), + pyo.units.get_units(m.fs.R3.costing.capital_cost), + ) + print( + "capital cost R4", + pyo.value(m.fs.R4.costing.capital_cost), + pyo.units.get_units(m.fs.R4.costing.capital_cost), + ) + print( + "capital cost R5", + pyo.value(m.fs.R5.costing.capital_cost), + pyo.units.get_units(m.fs.R5.costing.capital_cost), + ) + print( + "capital cost R6", + pyo.value(m.fs.R6.costing.capital_cost), + pyo.units.get_units(m.fs.R6.costing.capital_cost), + ) + print( + "capital cost R7", + pyo.value(m.fs.R7.costing.capital_cost), + pyo.units.get_units(m.fs.R7.costing.capital_cost), + ) + print( + "capital cost primary clarifier", + pyo.value(m.fs.CL.costing.capital_cost), + pyo.units.get_units(m.fs.CL.costing.capital_cost), + ) + print( + "capital cost secondary clarifier", + pyo.value(m.fs.CL2.costing.capital_cost), + pyo.units.get_units(m.fs.CL2.costing.capital_cost), + ) + print( + "capital cost AD", + pyo.value(m.fs.AD.costing.capital_cost), + pyo.units.get_units(m.fs.AD.costing.capital_cost), + ) + print( + "capital cost dewatering Unit", + pyo.value(m.fs.dewater.costing.capital_cost), + pyo.units.get_units(m.fs.dewater.costing.capital_cost), + ) + print( + "capital cost thickener unit", + pyo.value(m.fs.thickener.costing.capital_cost), + pyo.units.get_units(m.fs.thickener.costing.capital_cost), + ) + + +def display_performance_metrics(m): + print( + "Specific energy consumption with respect to influent flowrate: %.1f kWh/m3" + % pyo.value(m.fs.costing.specific_energy_consumption) + ) + + print( + "electricity consumption R5", + pyo.value(m.fs.R5.electricity_consumption[0]), + pyo.units.get_units(m.fs.R5.electricity_consumption[0]), + ) + print( + "electricity consumption R6", + pyo.value(m.fs.R6.electricity_consumption[0]), + pyo.units.get_units(m.fs.R6.electricity_consumption[0]), + ) + print( + "electricity consumption R7", + pyo.value(m.fs.R7.electricity_consumption[0]), + pyo.units.get_units(m.fs.R7.electricity_consumption[0]), + ) + print( + "electricity consumption primary clarifier", + pyo.value(m.fs.CL.electricity_consumption[0]), + pyo.units.get_units(m.fs.CL.electricity_consumption[0]), + ) + print( + "electricity consumption secondary clarifier", + pyo.value(m.fs.CL2.electricity_consumption[0]), + pyo.units.get_units(m.fs.CL2.electricity_consumption[0]), + ) + print( + "electricity consumption AD", + pyo.value(m.fs.AD.electricity_consumption[0]), + pyo.units.get_units(m.fs.AD.electricity_consumption[0]), + ) + print( + "electricity consumption dewatering Unit", + pyo.value(m.fs.dewater.electricity_consumption[0]), + pyo.units.get_units(m.fs.dewater.electricity_consumption[0]), + ) + print( + "electricity consumption thickening Unit", + pyo.value(m.fs.thickener.electricity_consumption[0]), + pyo.units.get_units(m.fs.thickener.electricity_consumption[0]), + ) + print( + "Influent flow", + pyo.value(m.fs.FeedWater.flow_vol[0]), + pyo.units.get_units(m.fs.FeedWater.flow_vol[0]), + ) + print( + "flow into R3", + pyo.value(m.fs.R3.control_volume.properties_in[0].flow_vol), + pyo.units.get_units(m.fs.R3.control_volume.properties_in[0].flow_vol), + ) + print( + "flow into RADM", + pyo.value(m.fs.AD.liquid_phase.properties_in[0].flow_vol), + pyo.units.get_units(m.fs.AD.liquid_phase.properties_in[0].flow_vol), + ) if __name__ == "__main__": diff --git a/watertap/flowsheets/full_water_resource_recovery_facility/BSM2_P_extension_ui.py b/watertap/flowsheets/full_water_resource_recovery_facility/BSM2_P_extension_ui.py index 28553c048c..5f5b1e4064 100644 --- a/watertap/flowsheets/full_water_resource_recovery_facility/BSM2_P_extension_ui.py +++ b/watertap/flowsheets/full_water_resource_recovery_facility/BSM2_P_extension_ui.py @@ -24,10 +24,13 @@ set_operating_conditions, initialize_system, solve, - # add_costing, + add_costing, ) -# from watertap.core.util.initialization import assert_degrees_of_freedom +from watertap.core.util.initialization import ( + assert_degrees_of_freedom, + interval_initializer, +) # Set up logger _log = idaeslog.getLogger(__name__) @@ -816,210 +819,210 @@ def export_variables(flowsheet=None, exports=None, build_options=None, **kwargs) is_output=False, ) - # # System costing - # exports.add( - # obj=fs.costing.utilization_factor, - # name="Utilization factor", - # ui_units=pyunits.dimensionless, - # display_units="fraction", - # rounding=2, - # description="Utilization factor - [annual use hours/total hours in year]", - # is_input=True, - # input_category="System costing", - # is_output=False, - # ) - # exports.add( - # obj=fs.costing.TIC, - # name="Practical investment factor", - # ui_units=pyunits.dimensionless, - # display_units="fraction", - # rounding=1, - # description="Practical investment factor - [total investment cost/direct " - # "capital costs]", - # is_input=True, - # input_category="System costing", - # is_output=False, - # ) - # exports.add( - # obj=fs.costing.plant_lifetime, - # name="Plant lifetime", - # ui_units=pyunits.year, - # display_units="years", - # rounding=1, - # description="Plant lifetime", - # is_input=True, - # input_category="System costing", - # is_output=False, - # ) - # exports.add( - # obj=fs.costing.wacc, - # name="Discount rate", - # ui_units=pyunits.dimensionless, - # display_units="fraction", - # rounding=2, - # description="Discount rate used in calculating the capital annualization", - # is_input=True, - # input_category="System costing", - # is_output=False, - # ) - # exports.add( - # obj=fs.costing.electricity_cost, - # name="Electricity cost", - # ui_units=fs.costing.base_currency / pyunits.kWh, - # display_units="$/kWh", - # rounding=3, - # description="Electricity cost", - # is_input=True, - # input_category="System costing", - # is_output=False, - # ) - # - # # Cost metrics - # exports.add( - # obj=fs.costing.LCOW, - # name="Levelized cost of water", - # ui_units=fs.costing.base_currency / pyunits.m**3, - # display_units="$/m3", - # rounding=3, - # description="Levelized cost of water with respect to product water", - # is_input=False, - # is_output=True, - # output_category="Cost metrics", - # ) - # exports.add( - # obj=fs.costing.total_operating_cost, - # name="Total operating cost", - # ui_units=fs.costing.base_currency / pyunits.yr, - # display_units="$/yr", - # rounding=3, - # description="Total operating cost", - # is_input=False, - # is_output=True, - # output_category="Cost metrics", - # ) - # exports.add( - # obj=fs.costing.total_capital_cost, - # name="Total capital cost", - # ui_units=fs.costing.base_currency, - # display_units="$", - # rounding=3, - # description="Total capital cost", - # is_input=False, - # is_output=True, - # output_category="Cost metrics", - # ) - # exports.add( - # obj=fs.costing.total_annualized_cost, - # name="Total annualized cost", - # ui_units=fs.costing.base_currency / pyunits.yr, - # display_units="$/yr", - # rounding=3, - # description="Total annualized cost", - # is_input=False, - # is_output=True, - # output_category="Cost metrics", - # ) - # exports.add( - # obj=fs.costing.specific_energy_consumption, - # name="Specific energy consumption", - # ui_units=pyunits.kWh / pyunits.m**3, - # display_units="kWh/m3", - # rounding=3, - # description="Specific energy consumption with respect to influent flowrate", - # is_input=False, - # is_output=True, - # output_category="Cost metrics", - # ) - # - # # Capital costs - # exports.add( - # obj=fs.R1.costing.capital_cost, - # name="Reactor 1 capital cost", - # ui_units=fs.costing.base_currency, - # display_units="$", - # rounding=3, - # description="Capital cost of first reactor in activated sludge process", - # is_input=False, - # is_output=True, - # output_category="Capital costs", - # ) - # exports.add( - # obj=fs.R2.costing.capital_cost, - # name="Reactor 2 capital cost", - # ui_units=fs.costing.base_currency, - # display_units="$", - # rounding=3, - # description="Capital cost of second reactor in activated sludge process", - # is_input=False, - # is_output=True, - # output_category="Capital costs", - # ) - # exports.add( - # obj=fs.R3.costing.capital_cost, - # name="Reactor 3 capital cost", - # ui_units=fs.costing.base_currency, - # display_units="$", - # rounding=3, - # description="Capital cost of third reactor in activated sludge process", - # is_input=False, - # is_output=True, - # output_category="Capital costs", - # ) - # exports.add( - # obj=fs.R4.costing.capital_cost, - # name="Reactor 4 capital cost", - # ui_units=fs.costing.base_currency, - # display_units="$", - # rounding=3, - # description="Capital cost of fourth reactor in activated sludge process", - # is_input=False, - # is_output=True, - # output_category="Capital costs", - # ) - # exports.add( - # obj=fs.R5.costing.capital_cost, - # name="Reactor 5 capital cost", - # ui_units=fs.costing.base_currency, - # display_units="$", - # rounding=3, - # description="Capital cost of fifth reactor in activated sludge process", - # is_input=False, - # is_output=True, - # output_category="Capital costs", - # ) - # exports.add( - # obj=fs.R6.costing.capital_cost, - # name="Reactor 6 capital cost", - # ui_units=fs.costing.base_currency, - # display_units="$", - # rounding=3, - # description="Capital cost of sixth reactor in activated sludge process", - # is_input=False, - # is_output=True, - # output_category="Capital costs", - # ) - # exports.add( - # obj=fs.R7.costing.capital_cost, - # name="Reactor 7 capital cost", - # ui_units=fs.costing.base_currency, - # display_units="$", - # rounding=3, - # description="Capital cost of seventh reactor in activated sludge process", - # is_input=False, - # is_output=True, - # output_category="Capital costs", - # ) - # exports.add( - # obj=fs.CL.costing.capital_cost, - # name="Primary clarifier capital cost", - # ui_units=fs.costing.base_currency, - # display_units="$", - # rounding=3, - # description="Capital cost of primary clarifier", - # is_input=False, - # is_output=True, - # output_category="Capital costs", - # ) + # System costing + exports.add( + obj=fs.costing.utilization_factor, + name="Utilization factor", + ui_units=pyunits.dimensionless, + display_units="fraction", + rounding=2, + description="Utilization factor - [annual use hours/total hours in year]", + is_input=True, + input_category="System costing", + is_output=False, + ) + exports.add( + obj=fs.costing.TIC, + name="Practical investment factor", + ui_units=pyunits.dimensionless, + display_units="fraction", + rounding=1, + description="Practical investment factor - [total investment cost/direct " + "capital costs]", + is_input=True, + input_category="System costing", + is_output=False, + ) + exports.add( + obj=fs.costing.plant_lifetime, + name="Plant lifetime", + ui_units=pyunits.year, + display_units="years", + rounding=1, + description="Plant lifetime", + is_input=True, + input_category="System costing", + is_output=False, + ) + exports.add( + obj=fs.costing.wacc, + name="Discount rate", + ui_units=pyunits.dimensionless, + display_units="fraction", + rounding=2, + description="Discount rate used in calculating the capital annualization", + is_input=True, + input_category="System costing", + is_output=False, + ) + exports.add( + obj=fs.costing.electricity_cost, + name="Electricity cost", + ui_units=fs.costing.base_currency / pyunits.kWh, + display_units="$/kWh", + rounding=3, + description="Electricity cost", + is_input=True, + input_category="System costing", + is_output=False, + ) + + # Cost metrics + exports.add( + obj=fs.costing.LCOW, + name="Levelized cost of water", + ui_units=fs.costing.base_currency / pyunits.m**3, + display_units="$/m3", + rounding=3, + description="Levelized cost of water with respect to product water", + is_input=False, + is_output=True, + output_category="Cost metrics", + ) + exports.add( + obj=fs.costing.total_operating_cost, + name="Total operating cost", + ui_units=fs.costing.base_currency / pyunits.yr, + display_units="$/yr", + rounding=3, + description="Total operating cost", + is_input=False, + is_output=True, + output_category="Cost metrics", + ) + exports.add( + obj=fs.costing.total_capital_cost, + name="Total capital cost", + ui_units=fs.costing.base_currency, + display_units="$", + rounding=3, + description="Total capital cost", + is_input=False, + is_output=True, + output_category="Cost metrics", + ) + exports.add( + obj=fs.costing.total_annualized_cost, + name="Total annualized cost", + ui_units=fs.costing.base_currency / pyunits.yr, + display_units="$/yr", + rounding=3, + description="Total annualized cost", + is_input=False, + is_output=True, + output_category="Cost metrics", + ) + exports.add( + obj=fs.costing.specific_energy_consumption, + name="Specific energy consumption", + ui_units=pyunits.kWh / pyunits.m**3, + display_units="kWh/m3", + rounding=3, + description="Specific energy consumption with respect to influent flowrate", + is_input=False, + is_output=True, + output_category="Cost metrics", + ) + + # Capital costs + exports.add( + obj=fs.R1.costing.capital_cost, + name="Reactor 1 capital cost", + ui_units=fs.costing.base_currency, + display_units="$", + rounding=3, + description="Capital cost of first reactor in activated sludge process", + is_input=False, + is_output=True, + output_category="Capital costs", + ) + exports.add( + obj=fs.R2.costing.capital_cost, + name="Reactor 2 capital cost", + ui_units=fs.costing.base_currency, + display_units="$", + rounding=3, + description="Capital cost of second reactor in activated sludge process", + is_input=False, + is_output=True, + output_category="Capital costs", + ) + exports.add( + obj=fs.R3.costing.capital_cost, + name="Reactor 3 capital cost", + ui_units=fs.costing.base_currency, + display_units="$", + rounding=3, + description="Capital cost of third reactor in activated sludge process", + is_input=False, + is_output=True, + output_category="Capital costs", + ) + exports.add( + obj=fs.R4.costing.capital_cost, + name="Reactor 4 capital cost", + ui_units=fs.costing.base_currency, + display_units="$", + rounding=3, + description="Capital cost of fourth reactor in activated sludge process", + is_input=False, + is_output=True, + output_category="Capital costs", + ) + exports.add( + obj=fs.R5.costing.capital_cost, + name="Reactor 5 capital cost", + ui_units=fs.costing.base_currency, + display_units="$", + rounding=3, + description="Capital cost of fifth reactor in activated sludge process", + is_input=False, + is_output=True, + output_category="Capital costs", + ) + exports.add( + obj=fs.R6.costing.capital_cost, + name="Reactor 6 capital cost", + ui_units=fs.costing.base_currency, + display_units="$", + rounding=3, + description="Capital cost of sixth reactor in activated sludge process", + is_input=False, + is_output=True, + output_category="Capital costs", + ) + exports.add( + obj=fs.R7.costing.capital_cost, + name="Reactor 7 capital cost", + ui_units=fs.costing.base_currency, + display_units="$", + rounding=3, + description="Capital cost of seventh reactor in activated sludge process", + is_input=False, + is_output=True, + output_category="Capital costs", + ) + exports.add( + obj=fs.CL.costing.capital_cost, + name="Primary clarifier capital cost", + ui_units=fs.costing.base_currency, + display_units="$", + rounding=3, + description="Capital cost of primary clarifier", + is_input=False, + is_output=True, + output_category="Capital costs", + ) # exports.add( # obj=fs.CL2.costing.capital_cost, # name="Secondary clarifier capital cost", @@ -3863,7 +3866,7 @@ def build_flowsheet(build_options=None, **kwargs): """ if build_options is not None: - if build_options["BioP"].value: + if build_options["BioP"]: bioP = True else: bioP = False @@ -3897,12 +3900,14 @@ def build_flowsheet(build_options=None, **kwargs): # Resolve with controls in place solve(m) - # add_costing(m) - # m.fs.costing.initialize() - # - # assert_degrees_of_freedom(m, 0) - # - # solve(m) + add_costing(m) + m.fs.costing.initialize() + + # interval_initializer(m.fs.costing) + + assert_degrees_of_freedom(m, 0) + + solve(m) else: m = build(bio_P=False) @@ -3934,12 +3939,14 @@ def build_flowsheet(build_options=None, **kwargs): # Resolve with controls in place solve(m) - # add_costing(m) - # m.fs.costing.initialize() - # - # assert_degrees_of_freedom(m, 0) - # - # solve(m) + add_costing(m) + m.fs.costing.initialize() + + interval_initializer(m.fs.costing) + + assert_degrees_of_freedom(m, 0) + + solve(m) return m diff --git a/watertap/flowsheets/full_water_resource_recovery_facility/test/test_BSM2_P_extension.py b/watertap/flowsheets/full_water_resource_recovery_facility/test/test_BSM2_P_extension.py index c4a78934af..f0eabc0af6 100644 --- a/watertap/flowsheets/full_water_resource_recovery_facility/test/test_BSM2_P_extension.py +++ b/watertap/flowsheets/full_water_resource_recovery_facility/test/test_BSM2_P_extension.py @@ -112,19 +112,19 @@ def test_solve(self, system_frame): 0.00021570, rel=1e-3 ) - # @pytest.mark.requires_idaes_solver - # @pytest.mark.component - # def test_costing(self, system_frame): - # m = system_frame - # - # # check costing - # assert value(m.fs.costing.LCOW) == pytest.approx(0.469988, rel=1e-3) - # assert value(m.fs.costing.total_capital_cost) == pytest.approx( - # 24033383.02, rel=1e-3 - # ) - # assert value(m.fs.costing.total_operating_cost) == pytest.approx( - # 831075.961, rel=1e-3 - # ) + @pytest.mark.requires_idaes_solver + @pytest.mark.component + def test_costing(self, system_frame): + m = system_frame + + # check costing + assert value(m.fs.costing.LCOW) == pytest.approx(0.468069, rel=1e-3) + assert value(m.fs.costing.total_capital_cost) == pytest.approx( + 23935727.742, rel=1e-3 + ) + assert value(m.fs.costing.total_operating_cost) == pytest.approx( + 827635.25, rel=1e-3 + ) class TestFullFlowsheetBioPTrue: @@ -205,16 +205,16 @@ def test_solve(self, system_frame): 0.00022424, rel=1e-3 ) - # @pytest.mark.requires_idaes_solver - # @pytest.mark.component - # def test_costing(self, system_frame): - # m = system_frame - # - # # check costing - # assert value(m.fs.costing.LCOW) == pytest.approx(0.47146, rel=1e-3) - # assert value(m.fs.costing.total_capital_cost) == pytest.approx( - # 24108366.80, rel=1e-3 - # ) - # assert value(m.fs.costing.total_operating_cost) == pytest.approx( - # 833724.746, rel=1e-3 - # ) + @pytest.mark.requires_idaes_solver + @pytest.mark.component + def test_costing(self, system_frame): + m = system_frame + + # check costing + assert value(m.fs.costing.LCOW) == pytest.approx(0.469711, rel=1e-3) + assert value(m.fs.costing.total_capital_cost) == pytest.approx( + 24019261.867, rel=1e-3 + ) + assert value(m.fs.costing.total_operating_cost) == pytest.approx( + 830582.94, rel=1e-3 + )