From 95b850fd42036f4f48df1863f7bf8a308827c3d3 Mon Sep 17 00:00:00 2001 From: softwareengineerprogrammer <4056124+softwareengineerprogrammer@users.noreply.github.com> Date: Thu, 31 Jul 2025 08:37:58 -0700 Subject: [PATCH 1/6] WIP - initial impl - examples not yet updated - FIXME, LCOH calculation broken somewhere --- src/geophires_x/Economics.py | 99 ++++++++++++++++++++++++------------ src/geophires_x/Outputs.py | 8 ++- 2 files changed, 73 insertions(+), 34 deletions(-) diff --git a/src/geophires_x/Economics.py b/src/geophires_x/Economics.py index d7ad098e..f389f65a 100644 --- a/src/geophires_x/Economics.py +++ b/src/geophires_x/Economics.py @@ -1,5 +1,8 @@ +from __future__ import annotations + import math import sys +# noinspection PyPackageRequirements import numpy as np import numpy_financial as npf from pint.facets.plain import PlainQuantity @@ -349,7 +352,7 @@ def CalculateFinancialPerformance(plantlifetime: int, return NPV, IRR, VIR, MOIC -def CalculateLCOELCOHLCOC(econ, model: Model) -> tuple: +def CalculateLCOELCOHLCOC(econ, model: Model) -> tuple[float, float, float]: """ CalculateLCOELCOH calculates the levelized cost of electricity and heat for the project. :param econ: Economics object @@ -357,21 +360,42 @@ def CalculateLCOELCOHLCOC(econ, model: Model) -> tuple: :param model: The model object :type model: :class:`~geophires_x.Model.Model` :return: LCOE: The levelized cost of electricity and LCOH: The levelized cost of heat and LCOC: The levelized cost of cooling - :rtype: tuple + :rtype: tuple[float, float, float] """ LCOE = LCOH = LCOC = 0.0 CCap_elec = (econ.CCap.value * econ.CAPEX_heat_electricity_plant_ratio.value) Coam_elec = (econ.Coam.value * econ.CAPEX_heat_electricity_plant_ratio.value) CCap_heat = (econ.CCap.value * (1.0 - econ.CAPEX_heat_electricity_plant_ratio.value)) Coam_heat = (econ.Coam.value * (1.0 - econ.CAPEX_heat_electricity_plant_ratio.value)) + + def _capex_total_plus_construction_inflation() -> float: + # TODO unit conversions + # TODO should be return value instead of mutating econ + econ.inflation_cost_during_construction.value = econ.CCap.value * econ.inflrateconstruction.value + + return econ.CCap.value + econ.inflation_cost_during_construction.value + + def _construction_inflation_cost_elec_heat() -> tuple[float, float]: + # TODO unit conversions + construction_inflation_cost_elec = CCap_elec * econ.inflrateconstruction.value + construction_inflation_cost_heat = CCap_heat * econ.inflrateconstruction.value + + # TODO should be return value instead of mutating econ + econ.inflation_cost_during_construction.value = (construction_inflation_cost_elec + + construction_inflation_cost_heat) + + return CCap_elec + construction_inflation_cost_elec, CCap_heat + construction_inflation_cost_heat + # Calculate LCOE/LCOH/LCOC if econ.econmodel.value == EconomicModel.FCR: + capex_total_plus_infl = _capex_total_plus_construction_inflation() + if model.surfaceplant.enduse_option.value == EndUseOptions.ELECTRICITY: - LCOE = (econ.FCR.value * (1 + econ.inflrateconstruction.value) * econ.CCap.value + econ.Coam.value) / \ + LCOE = (econ.FCR.value * capex_total_plus_infl + econ.Coam.value) / \ np.average(model.surfaceplant.NetkWhProduced.value) * 1E8 # cents/kWh elif (model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value not in [PlantType.ABSORPTION_CHILLER, PlantType.HEAT_PUMP, PlantType.DISTRICT_HEATING]): - LCOH = (econ.FCR.value * (1 + econ.inflrateconstruction.value) * econ.CCap.value + econ.Coam.value + + LCOH = (econ.FCR.value * capex_total_plus_infl + econ.Coam.value + econ.averageannualpumpingcosts.value) / np.average( model.surfaceplant.HeatkWhProduced.value) * 1E8 # cents/kWh LCOH = LCOH * 2.931 # $/Million Btu @@ -382,38 +406,40 @@ def CalculateLCOELCOHLCOC(econ, model: Model) -> tuple: EndUseOptions.COGENERATION_BOTTOMING_EXTRA_HEAT, EndUseOptions.COGENERATION_PARALLEL_EXTRA_HEAT, EndUseOptions.COGENERATION_PARALLEL_EXTRA_ELECTRICITY]: - LCOE = (econ.FCR.value * (1 + econ.inflrateconstruction.value) * CCap_elec + Coam_elec) / np.average(model.surfaceplant.NetkWhProduced.value) * 1E8 # cents/kWh - LCOH = (econ.FCR.value * (1 + econ.inflrateconstruction.value) * CCap_heat + Coam_heat + econ.averageannualpumpingcosts.value) / np.average(model.surfaceplant.HeatkWhProduced.value) * 1E8 # cents/kWh + capex_elec_plus_infl, capex_heat_plus_infl = _construction_inflation_cost_elec_heat() + LCOE = (econ.FCR.value * capex_elec_plus_infl + Coam_elec) / np.average(model.surfaceplant.NetkWhProduced.value) * 1E8 # cents/kWh + LCOH = (econ.FCR.value * capex_heat_plus_infl + Coam_heat + econ.averageannualpumpingcosts.value) / np.average(model.surfaceplant.HeatkWhProduced.value) * 1E8 # cents/kWh LCOH = LCOH * 2.931 # $/Million Btu elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value == PlantType.ABSORPTION_CHILLER: - LCOC = (econ.FCR.value * ( - 1 + econ.inflrateconstruction.value) * econ.CCap.value + econ.Coam.value + econ.averageannualpumpingcosts.value) / np.average( + LCOC = (econ.FCR.value * capex_total_plus_infl + econ.Coam.value + econ.averageannualpumpingcosts.value) / np.average( model.surfaceplant.cooling_kWh_Produced.value) * 1E8 # cents/kWh LCOC = LCOC * 2.931 # $/Million Btu elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value == PlantType.HEAT_PUMP: - LCOH = (econ.FCR.value * ( - 1 + econ.inflrateconstruction.value) * econ.CCap.value + econ.Coam.value + econ.averageannualpumpingcosts.value + econ.averageannualheatpumpelectricitycost.value) / np.average( + LCOH = (econ.FCR.value * capex_total_plus_infl + + econ.Coam.value + econ.averageannualpumpingcosts.value + econ.averageannualheatpumpelectricitycost.value) / np.average( model.surfaceplant.HeatkWhProduced.value) * 1E8 # cents/kWh LCOH = LCOH * 2.931 # $/Million Btu elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value == PlantType.DISTRICT_HEATING: - LCOH = (econ.FCR.value * ( - 1 + econ.inflrateconstruction.value) * econ.CCap.value + econ.Coam.value + econ.averageannualpumpingcosts.value + econ.averageannualngcost.value) / model.surfaceplant.annual_heating_demand.value * 1E2 # cents/kWh + LCOH = (econ.FCR.value * capex_total_plus_infl + + econ.Coam.value + econ.averageannualpumpingcosts.value + econ.averageannualngcost.value) / model.surfaceplant.annual_heating_demand.value * 1E2 # cents/kWh LCOH = LCOH * 2.931 # $/Million Btu elif econ.econmodel.value == EconomicModel.STANDARDIZED_LEVELIZED_COST: discount_vector = 1. / np.power(1 + econ.discountrate.value, np.linspace(0, model.surfaceplant.plant_lifetime.value - 1, model.surfaceplant.plant_lifetime.value)) + capex_total_plus_infl = _capex_total_plus_construction_inflation() + if model.surfaceplant.enduse_option.value == EndUseOptions.ELECTRICITY: - LCOE = ((1 + econ.inflrateconstruction.value) * econ.CCap.value + np.sum( + LCOE = (capex_total_plus_infl + np.sum( econ.Coam.value * discount_vector)) / np.sum( model.surfaceplant.NetkWhProduced.value * discount_vector) * 1E8 # cents/kWh elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and \ model.surfaceplant.plant_type.value not in [PlantType.ABSORPTION_CHILLER, PlantType.HEAT_PUMP, PlantType.DISTRICT_HEATING]: econ.averageannualpumpingcosts.value = np.average( model.surfaceplant.PumpingkWh.value) * model.surfaceplant.electricity_cost_to_buy.value / 1E6 # M$/year - LCOH = ((1 + econ.inflrateconstruction.value) * econ.CCap.value + np.sum(( - econ.Coam.value + model.surfaceplant.PumpingkWh.value * model.surfaceplant.electricity_cost_to_buy.value / 1E6) * discount_vector)) / np.sum( + LCOH = (capex_total_plus_infl + np.sum(( + econ.Coam.value + model.surfaceplant.PumpingkWh.value * model.surfaceplant.electricity_cost_to_buy.value / 1E6) * discount_vector)) / np.sum( model.surfaceplant.HeatkWhProduced.value * discount_vector) * 1E8 # cents/kWh LCOH = LCOH * 2.931 # $/MMBTU @@ -424,24 +450,30 @@ def CalculateLCOELCOHLCOC(econ, model: Model) -> tuple: EndUseOptions.COGENERATION_BOTTOMING_EXTRA_HEAT, EndUseOptions.COGENERATION_PARALLEL_EXTRA_HEAT, EndUseOptions.COGENERATION_PARALLEL_EXTRA_ELECTRICITY]: - LCOE = ((1 + econ.inflrateconstruction.value) * CCap_elec + np.sum(Coam_elec * discount_vector)) / np.sum(model.surfaceplant.NetkWhProduced.value * discount_vector) * 1E8 # cents/kWh - LCOH = ((1 + econ.inflrateconstruction.value) * CCap_heat + + capex_elec_plus_infl, capex_heat_plus_infl = _construction_inflation_cost_elec_heat() + + LCOE = (capex_elec_plus_infl + np.sum(Coam_elec * discount_vector)) / np.sum(model.surfaceplant.NetkWhProduced.value * discount_vector) * 1E8 # cents/kWh + LCOH = (capex_heat_plus_infl * CCap_heat + np.sum((Coam_heat + model.surfaceplant.PumpingkWh.value * model.surfaceplant.electricity_cost_to_buy.value / 1E6) * discount_vector)) / np.sum(model.surfaceplant.HeatkWhProduced.value * discount_vector) * 1E8 # cents/kWh LCOH = LCOH * 2.931 # $/MMBTU elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value == PlantType.ABSORPTION_CHILLER: - LCOC = ((1 + econ.inflrateconstruction.value) * econ.CCap.value + np.sum(( - econ.Coam.value + model.surfaceplant.PumpingkWh.value * model.surfaceplant.electricity_cost_to_buy.value / 1E6) * discount_vector)) / np.sum( + capex_total_plus_infl = _capex_total_plus_construction_inflation() + + LCOC = (capex_total_plus_infl + np.sum(( + econ.Coam.value + model.surfaceplant.PumpingkWh.value * model.surfaceplant.electricity_cost_to_buy.value / 1E6) * discount_vector)) / np.sum( model.surfaceplant.cooling_kWh_Produced.value * discount_vector) * 1E8 # cents/kWh LCOC = LCOC * 2.931 # $/Million Btu elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value == PlantType.HEAT_PUMP: - LCOH = ((1 + econ.inflrateconstruction.value) * econ.CCap.value + np.sum( + capex_total_plus_infl = _capex_total_plus_construction_inflation() + LCOH = (capex_total_plus_infl + np.sum( (econ.Coam.value + model.surfaceplant.PumpingkWh.value * model.surfaceplant.electricity_cost_to_buy.value / 1E6 + model.surfaceplant.heat_pump_electricity_kwh_used.value * model.surfaceplant.electricity_cost_to_buy.value / 1E6) * discount_vector)) / np.sum( model.surfaceplant.HeatkWhProduced.value * discount_vector) * 1E8 # cents/kWh LCOH = LCOH * 2.931 # $/Million Btu elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value == PlantType.DISTRICT_HEATING: - LCOH = ((1 + econ.inflrateconstruction.value) * econ.CCap.value + np.sum( + capex_total_plus_infl = _capex_total_plus_construction_inflation() + LCOH = (capex_total_plus_infl + np.sum( (econ.Coam.value + model.surfaceplant.PumpingkWh.value * model.surfaceplant.electricity_cost_to_buy.value / 1E6 + econ.annualngcost.value) * discount_vector)) / np.sum( model.surfaceplant.annual_heating_demand.value * discount_vector) * 1E2 # cents/kWh @@ -457,10 +489,12 @@ def CalculateLCOELCOHLCOC(econ, model: Model) -> tuple: CRF = i_ave / (1 - np.power(1 + i_ave, -model.surfaceplant.plant_lifetime.value)) inflation_vector = np.power(1 + econ.RINFL.value, np.linspace(1, model.surfaceplant.plant_lifetime.value, model.surfaceplant.plant_lifetime.value)) discount_vector = 1. / np.power(1 + i_ave, np.linspace(1, model.surfaceplant.plant_lifetime.value, model.surfaceplant.plant_lifetime.value)) - NPV_cap = np.sum((1 + econ.inflrateconstruction.value) * econ.CCap.value * CRF * discount_vector) - NPV_fc = np.sum((1 + econ.inflrateconstruction.value) * econ.CCap.value * econ.PTR.value * inflation_vector * discount_vector) - NPV_it = np.sum(econ.CTR.value / (1 - econ.CTR.value) * ((1 + econ.inflrateconstruction.value) * econ.CCap.value * CRF - econ.CCap.value / model.surfaceplant.plant_lifetime.value) * discount_vector) - NPV_itc = (1 + econ.inflrateconstruction.value) * econ.CCap.value * econ.RITC.value / (1 - econ.CTR.value) + capex_total_plus_infl = _capex_total_plus_construction_inflation() + + NPV_cap = np.sum(capex_total_plus_infl * CRF * discount_vector) + NPV_fc = np.sum(capex_total_plus_infl * econ.PTR.value * inflation_vector * discount_vector) + NPV_it = np.sum(econ.CTR.value / (1 - econ.CTR.value) * (capex_total_plus_infl * CRF - econ.CCap.value / model.surfaceplant.plant_lifetime.value) * discount_vector) + NPV_itc = capex_total_plus_infl * econ.RITC.value / (1 - econ.CTR.value) if model.surfaceplant.enduse_option.value == EndUseOptions.ELECTRICITY: NPV_oandm = np.sum(econ.Coam.value * inflation_vector * discount_vector) @@ -479,21 +513,22 @@ def CalculateLCOELCOHLCOC(econ, model: Model) -> tuple: EndUseOptions.COGENERATION_BOTTOMING_EXTRA_HEAT, EndUseOptions.COGENERATION_PARALLEL_EXTRA_HEAT, EndUseOptions.COGENERATION_PARALLEL_EXTRA_ELECTRICITY]: + capex_elec_plus_infl, capex_heat_plus_infl = _construction_inflation_cost_elec_heat() - NPVcap_elec = np.sum((1 + econ.inflrateconstruction.value) * CCap_elec * CRF * discount_vector) - NPVfc_elec = np.sum((1 + econ.inflrateconstruction.value) * CCap_elec * econ.PTR.value * inflation_vector * discount_vector) - NPVit_elec = np.sum(econ.CTR.value / (1 - econ.CTR.value) * ((1 + econ.inflrateconstruction.value) * CCap_elec * CRF - CCap_elec / model.surfaceplant.plant_lifetime.value) * discount_vector) - NPVitc_elec = (1 + econ.inflrateconstruction.value) * CCap_elec * econ.RITC.value / (1 - econ.CTR.value) + NPVcap_elec = np.sum(capex_elec_plus_infl * CRF * discount_vector) + NPVfc_elec = np.sum(capex_elec_plus_infl * econ.PTR.value * inflation_vector * discount_vector) + NPVit_elec = np.sum(econ.CTR.value / (1 - econ.CTR.value) * (capex_elec_plus_infl * CRF - CCap_elec / model.surfaceplant.plant_lifetime.value) * discount_vector) + NPVitc_elec = capex_elec_plus_infl * econ.RITC.value / (1 - econ.CTR.value) NPVoandm_elec = np.sum(Coam_elec * inflation_vector * discount_vector) NPVgrt_elec = econ.GTR.value / (1 - econ.GTR.value) * (NPVcap_elec + NPVoandm_elec + NPVfc_elec + NPVit_elec - NPVitc_elec) LCOE = ((NPVcap_elec + NPVoandm_elec + NPVfc_elec + NPVit_elec + NPVgrt_elec - NPVitc_elec) / np.sum(model.surfaceplant.NetkWhProduced.value * inflation_vector * discount_vector) * 1E8) - NPV_cap_heat = np.sum((1 + econ.inflrateconstruction.value) * CCap_heat * CRF * discount_vector) + NPV_cap_heat = np.sum(capex_heat_plus_infl * CRF * discount_vector) NPV_fc_heat = np.sum((1 + econ.inflrateconstruction.value) * (econ.CCap.value * (1.0 - econ.CAPEX_heat_electricity_plant_ratio.value)) * econ.PTR.value * inflation_vector * discount_vector) - NPV_it_heat = np.sum(econ.CTR.value / (1 - econ.CTR.value) * ((1 + econ.inflrateconstruction.value) * CCap_heat * CRF - CCap_heat / model.surfaceplant.plant_lifetime.value) * discount_vector) - NPV_itc_heat = (1 + econ.inflrateconstruction.value) * CCap_heat * econ.RITC.value / (1 - econ.CTR.value) + NPV_it_heat = np.sum(econ.CTR.value / (1 - econ.CTR.value) * (capex_heat_plus_infl * CRF - CCap_heat / model.surfaceplant.plant_lifetime.value) * discount_vector) + NPV_itc_heat = capex_heat_plus_infl * econ.RITC.value / (1 - econ.CTR.value) NPV_oandm_heat = np.sum((econ.Coam.value * (1.0 - econ.CAPEX_heat_electricity_plant_ratio.value)) * inflation_vector * discount_vector) NPV_grt_heat = econ.GTR.value / (1 - econ.GTR.value) * (NPV_cap_heat + NPV_oandm_heat + NPV_fc_heat + NPV_it_heat - NPV_itc_heat) diff --git a/src/geophires_x/Outputs.py b/src/geophires_x/Outputs.py index dd0b6857..41c2536d 100644 --- a/src/geophires_x/Outputs.py +++ b/src/geophires_x/Outputs.py @@ -497,8 +497,12 @@ def PrintOutputs(self, model: Model): # expenditure. pass - if is_sam_econ_model: - # TODO calculate & display for other economic models + display_inflation_during_construction_in_capital_costs = is_sam_econ_model \ + or (econ.econmodel.value in [EconomicModel.BICYCLE, EconomicModel.FCR, + EconomicModel.STANDARDIZED_LEVELIZED_COST] + and + econ.inflation_cost_during_construction.value != 0.) + if display_inflation_during_construction_in_capital_costs: icc_label = Outputs._field_label(econ.inflation_cost_during_construction.display_name, 47) f.write(f' {icc_label}{econ.inflation_cost_during_construction.value:10.2f} {econ.inflation_cost_during_construction.CurrentUnits.value}\n') From b44fda1ef0c2de07d23a91ac1ec43914c1a354d1 Mon Sep 17 00:00:00 2001 From: softwareengineerprogrammer <4056124+softwareengineerprogrammer@users.noreply.github.com> Date: Thu, 31 Jul 2025 08:42:15 -0700 Subject: [PATCH 2/6] Update examples that correctly have inflation costs during construction added to Capital Costs - TODO to display this in ECONOMIC PARAMETERS instead --- tests/examples/Fervo_Norbeck_Latimer_2023.out | 11 ++++++----- tests/examples/Fervo_Project_Cape-2.out | 11 ++++++----- tests/examples/Fervo_Project_Cape-3.out | 11 ++++++----- tests/examples/Fervo_Project_Cape.out | 11 ++++++----- tests/examples/example10_HP.out | 13 +++++++------ tests/examples/example11_AC.out | 13 +++++++------ tests/examples/example3.out | 13 +++++++------ 7 files changed, 45 insertions(+), 38 deletions(-) diff --git a/tests/examples/Fervo_Norbeck_Latimer_2023.out b/tests/examples/Fervo_Norbeck_Latimer_2023.out index f133e97a..4388a9b7 100644 --- a/tests/examples/Fervo_Norbeck_Latimer_2023.out +++ b/tests/examples/Fervo_Norbeck_Latimer_2023.out @@ -4,10 +4,10 @@ Simulation Metadata ---------------------- - GEOPHIRES Version: 3.9.28 - Simulation Date: 2025-07-02 - Simulation Time: 12:19 - Calculation Time: 0.481 sec + GEOPHIRES Version: 3.9.47 + Simulation Date: 2025-07-31 + Simulation Time: 08:38 + Calculation Time: 0.476 sec ***SUMMARY OF RESULTS*** @@ -24,7 +24,7 @@ Simulation Metadata ***ECONOMIC PARAMETERS*** Economic Model = BICYCLE - Accrued financing during construction: 5.00 % + Accrued financing during construction: 5.00 % Project lifetime: 10 yr Capacity factor: 90.0 % Project NPV: -13.03 MUSD @@ -103,6 +103,7 @@ Simulation Metadata Field gathering system costs: 1.52 MUSD Total surface equipment costs: 12.85 MUSD Exploration costs: 3.62 MUSD + Inflation costs during construction: 1.41 MUSD Total capital costs: 28.12 MUSD diff --git a/tests/examples/Fervo_Project_Cape-2.out b/tests/examples/Fervo_Project_Cape-2.out index f4debd0d..5c358377 100644 --- a/tests/examples/Fervo_Project_Cape-2.out +++ b/tests/examples/Fervo_Project_Cape-2.out @@ -4,10 +4,10 @@ Simulation Metadata ---------------------- - GEOPHIRES Version: 3.9.28 - Simulation Date: 2025-07-02 - Simulation Time: 12:19 - Calculation Time: 0.722 sec + GEOPHIRES Version: 3.9.47 + Simulation Date: 2025-07-31 + Simulation Time: 08:38 + Calculation Time: 0.707 sec ***SUMMARY OF RESULTS*** @@ -24,7 +24,7 @@ Simulation Metadata ***ECONOMIC PARAMETERS*** Economic Model = BICYCLE - Accrued financing during construction: 5.00 % + Accrued financing during construction: 5.00 % Project lifetime: 15 yr Capacity factor: 90.0 % Project NPV: 42.34 MUSD @@ -101,6 +101,7 @@ Simulation Metadata Field gathering system costs: 1.68 MUSD Total surface equipment costs: 26.36 MUSD Exploration costs: 0.00 MUSD + Inflation costs during construction: 2.54 MUSD Total capital costs: 50.76 MUSD diff --git a/tests/examples/Fervo_Project_Cape-3.out b/tests/examples/Fervo_Project_Cape-3.out index 93f1c996..93cade9e 100644 --- a/tests/examples/Fervo_Project_Cape-3.out +++ b/tests/examples/Fervo_Project_Cape-3.out @@ -4,10 +4,10 @@ Simulation Metadata ---------------------- - GEOPHIRES Version: 3.9.28 - Simulation Date: 2025-07-02 - Simulation Time: 12:19 - Calculation Time: 0.956 sec + GEOPHIRES Version: 3.9.47 + Simulation Date: 2025-07-31 + Simulation Time: 08:38 + Calculation Time: 0.940 sec ***SUMMARY OF RESULTS*** @@ -24,7 +24,7 @@ Simulation Metadata ***ECONOMIC PARAMETERS*** Economic Model = BICYCLE - Accrued financing during construction: 5.00 % + Accrued financing during construction: 5.00 % Project lifetime: 20 yr Capacity factor: 90.0 % Project NPV: 4580.36 MUSD @@ -102,6 +102,7 @@ Simulation Metadata Total surface equipment costs: 969.26 MUSD Exploration costs: 30.00 MUSD Investment Tax Credit: -459.83 MUSD + Inflation costs during construction: 53.65 MUSD Total capital costs: 1072.95 MUSD diff --git a/tests/examples/Fervo_Project_Cape.out b/tests/examples/Fervo_Project_Cape.out index af4fa2e9..a4c3747f 100644 --- a/tests/examples/Fervo_Project_Cape.out +++ b/tests/examples/Fervo_Project_Cape.out @@ -4,10 +4,10 @@ Simulation Metadata ---------------------- - GEOPHIRES Version: 3.9.28 - Simulation Date: 2025-07-02 - Simulation Time: 12:19 - Calculation Time: 0.720 sec + GEOPHIRES Version: 3.9.47 + Simulation Date: 2025-07-31 + Simulation Time: 08:38 + Calculation Time: 0.707 sec ***SUMMARY OF RESULTS*** @@ -24,7 +24,7 @@ Simulation Metadata ***ECONOMIC PARAMETERS*** Economic Model = BICYCLE - Accrued financing during construction: 5.00 % + Accrued financing during construction: 5.00 % Project lifetime: 15 yr Capacity factor: 90.0 % Project NPV: 520.01 MUSD @@ -101,6 +101,7 @@ Simulation Metadata Field gathering system costs: 23.00 MUSD Total surface equipment costs: 357.63 MUSD Exploration costs: 0.00 MUSD + Inflation costs during construction: 24.14 MUSD Total capital costs: 482.83 MUSD diff --git a/tests/examples/example10_HP.out b/tests/examples/example10_HP.out index 51991cce..5107f2db 100644 --- a/tests/examples/example10_HP.out +++ b/tests/examples/example10_HP.out @@ -4,10 +4,10 @@ Simulation Metadata ---------------------- - GEOPHIRES Version: 3.9.7 - Simulation Date: 2025-05-15 - Simulation Time: 10:13 - Calculation Time: 0.096 sec + GEOPHIRES Version: 3.9.47 + Simulation Date: 2025-07-31 + Simulation Time: 08:38 + Calculation Time: 0.105 sec ***SUMMARY OF RESULTS*** @@ -26,7 +26,7 @@ Simulation Metadata Economic Model = Standard Levelized Cost Interest Rate: 5.00 % - Accrued financing during construction: 5.00 % + Accrued financing during construction: 5.00 % Project lifetime: 30 yr Capacity factor: 90.0 % Project NPV: 15.18 MUSD @@ -64,7 +64,7 @@ Simulation Metadata m/A Drawdown Parameter: 0.00002 1/year Bottom-hole temperature: 109.50 degC Reservoir volume calculated with fracture separation and number of fractures as input - Number of fractures: 12.00 + Number of fractures: 12 Fracture separation: 80.00 meter Reservoir volume: 176000000 m**3 Reservoir hydrostatic pressure: 20488.96 kPa @@ -99,6 +99,7 @@ Simulation Metadata Field gathering system costs: 2.55 MUSD Total surface equipment costs: 10.33 MUSD Exploration costs: 3.32 MUSD + Inflation costs during construction: 1.39 MUSD Total capital costs: 27.72 MUSD diff --git a/tests/examples/example11_AC.out b/tests/examples/example11_AC.out index 5cff8880..37915dba 100644 --- a/tests/examples/example11_AC.out +++ b/tests/examples/example11_AC.out @@ -4,10 +4,10 @@ Simulation Metadata ---------------------- - GEOPHIRES Version: 3.9.7 - Simulation Date: 2025-05-15 - Simulation Time: 10:13 - Calculation Time: 0.096 sec + GEOPHIRES Version: 3.9.47 + Simulation Date: 2025-07-31 + Simulation Time: 08:38 + Calculation Time: 0.107 sec ***SUMMARY OF RESULTS*** @@ -27,7 +27,7 @@ Simulation Metadata Economic Model = Standard Levelized Cost Interest Rate: 5.00 % - Accrued financing during construction: 5.00 % + Accrued financing during construction: 5.00 % Project lifetime: 30 yr Capacity factor: 90.0 % Project NPV: 10.11 MUSD @@ -65,7 +65,7 @@ Simulation Metadata m/A Drawdown Parameter: 0.00002 1/year Bottom-hole temperature: 109.50 degC Reservoir volume calculated with fracture separation and number of fractures as input - Number of fractures: 12.00 + Number of fractures: 12 Fracture separation: 80.00 meter Reservoir volume: 176000000 m**3 Reservoir hydrostatic pressure: 20488.96 kPa @@ -100,6 +100,7 @@ Simulation Metadata Field gathering system costs: 2.34 MUSD Total surface equipment costs: 8.96 MUSD Exploration costs: 3.32 MUSD + Inflation costs during construction: 1.32 MUSD Total capital costs: 26.35 MUSD diff --git a/tests/examples/example3.out b/tests/examples/example3.out index 01516178..b0f5a3c8 100644 --- a/tests/examples/example3.out +++ b/tests/examples/example3.out @@ -4,10 +4,10 @@ Simulation Metadata ---------------------- - GEOPHIRES Version: 3.9.7 - Simulation Date: 2025-05-15 - Simulation Time: 10:12 - Calculation Time: 0.113 sec + GEOPHIRES Version: 3.9.47 + Simulation Date: 2025-07-31 + Simulation Time: 08:38 + Calculation Time: 0.123 sec ***SUMMARY OF RESULTS*** @@ -26,7 +26,7 @@ Simulation Metadata ***ECONOMIC PARAMETERS*** Economic Model = BICYCLE - Accrued financing during construction: 5.00 % + Accrued financing during construction: 5.00 % Project lifetime: 35 yr Capacity factor: 90.0 % Project NPV: -2.38 MUSD @@ -66,7 +66,7 @@ Simulation Metadata m/A Drawdown Parameter: 0.00002 1/year Bottom-hole temperature: 232.00 degC Reservoir volume calculated with fracture separation and number of fractures as input - Number of fractures: 12.00 + Number of fractures: 12 Fracture separation: 80.00 meter Reservoir volume: 176000000 m**3 Reservoir hydrostatic pressure: 29019.48 kPa @@ -97,6 +97,7 @@ Simulation Metadata Field gathering system costs: 3.17 MUSD Total surface equipment costs: 67.22 MUSD Exploration costs: 4.64 MUSD + Inflation costs during construction: 5.18 MUSD Total capital costs: 103.68 MUSD From 02058cc2e29330f2b0cdb2183fd74f0fc856198b Mon Sep 17 00:00:00 2001 From: softwareengineerprogrammer <4056124+softwareengineerprogrammer@users.noreply.github.com> Date: Thu, 31 Jul 2025 08:45:06 -0700 Subject: [PATCH 3/6] fix impl error introduced in 95b850fd42036f4f48df1863f7bf8a308827c3d3 that was affecting example13 (regenerated with no change in results) --- src/geophires_x/Economics.py | 2 +- tests/examples/example13.out | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/geophires_x/Economics.py b/src/geophires_x/Economics.py index f389f65a..181a1677 100644 --- a/src/geophires_x/Economics.py +++ b/src/geophires_x/Economics.py @@ -453,7 +453,7 @@ def _construction_inflation_cost_elec_heat() -> tuple[float, float]: capex_elec_plus_infl, capex_heat_plus_infl = _construction_inflation_cost_elec_heat() LCOE = (capex_elec_plus_infl + np.sum(Coam_elec * discount_vector)) / np.sum(model.surfaceplant.NetkWhProduced.value * discount_vector) * 1E8 # cents/kWh - LCOH = (capex_heat_plus_infl * CCap_heat + + LCOH = (capex_heat_plus_infl + np.sum((Coam_heat + model.surfaceplant.PumpingkWh.value * model.surfaceplant.electricity_cost_to_buy.value / 1E6) * discount_vector)) / np.sum(model.surfaceplant.HeatkWhProduced.value * discount_vector) * 1E8 # cents/kWh LCOH = LCOH * 2.931 # $/MMBTU diff --git a/tests/examples/example13.out b/tests/examples/example13.out index 006909f4..7b881308 100644 --- a/tests/examples/example13.out +++ b/tests/examples/example13.out @@ -4,10 +4,10 @@ Simulation Metadata ---------------------- - GEOPHIRES Version: 3.9.36 - Simulation Date: 2025-07-25 - Simulation Time: 11:30 - Calculation Time: 0.037 sec + GEOPHIRES Version: 3.9.47 + Simulation Date: 2025-07-31 + Simulation Time: 08:44 + Calculation Time: 0.036 sec ***SUMMARY OF RESULTS*** @@ -27,7 +27,7 @@ Simulation Metadata Economic Model = Standard Levelized Cost Interest Rate: 5.00 % - Accrued financing during construction: 0.00 % + Accrued financing during construction: 0.00 % Project lifetime: 30 yr Capacity factor: 80.0 % Project NPV: -31.42 MUSD From a3cd9d27ca53278559bf36a682e1d92fc153358c Mon Sep 17 00:00:00 2001 From: softwareengineerprogrammer <4056124+softwareengineerprogrammer@users.noreply.github.com> Date: Thu, 31 Jul 2025 09:00:19 -0700 Subject: [PATCH 4/6] Output Inflation costs during construction in ECONOMIC PARAMETERS after Accrued financing during construction for economic models that don't treat inflation costs as capital costs (non-SAM-EM) --- src/geophires_x/EconomicsUtils.py | 8 ++++---- src/geophires_x/Outputs.py | 20 ++++++++++++++----- src/geophires_x_client/geophires_x_result.py | 3 +++ .../geophires-result.json | 9 +++++++-- tests/examples/Fervo_Norbeck_Latimer_2023.out | 6 +++--- tests/examples/Fervo_Project_Cape-2.out | 6 +++--- tests/examples/Fervo_Project_Cape-3.out | 6 +++--- tests/examples/Fervo_Project_Cape.out | 6 +++--- tests/examples/example10_HP.out | 4 ++-- tests/examples/example11_AC.out | 4 ++-- tests/examples/example3.out | 6 +++--- 11 files changed, 48 insertions(+), 30 deletions(-) diff --git a/src/geophires_x/EconomicsUtils.py b/src/geophires_x/EconomicsUtils.py index 71dd8c62..1f586a14 100644 --- a/src/geophires_x/EconomicsUtils.py +++ b/src/geophires_x/EconomicsUtils.py @@ -139,8 +139,8 @@ def total_capex_parameter_output_parameter() -> OutputParameter: UnitType=Units.CURRENCY, CurrentUnits=CurrencyUnit.MDOLLARS, PreferredUnits=CurrencyUnit.MDOLLARS, - ToolTipText="The total capital expenditure (CAPEX) required to construct the plant. " - "This value includes all direct and indirect costs, contingency, and any cost escalation from " - "inflation during construction. It is used as the total installed cost input for " - "SAM Economic Models." + ToolTipText='The total capital expenditure (CAPEX) required to construct the plant. ' + 'This value includes all direct and indirect costs, and contingency. ' + 'For SAM Economic models, it also includes any cost escalation from inflation during construction. ' + 'It is used as the total installed cost input for SAM Economic Models.' ) diff --git a/src/geophires_x/Outputs.py b/src/geophires_x/Outputs.py index 41c2536d..26c082fa 100644 --- a/src/geophires_x/Outputs.py +++ b/src/geophires_x/Outputs.py @@ -274,6 +274,20 @@ def PrintOutputs(self, model: Model): acf_label = Outputs._field_label(acf.display_name, 49) f.write(f' {acf_label}{acf.value:10.2f} {acf.CurrentUnits.value}\n') + display_inflation_costs_in_economic_parameters: bool = ( + econ.econmodel.value in [EconomicModel.BICYCLE, + EconomicModel.FCR, + EconomicModel.STANDARDIZED_LEVELIZED_COST] + and + econ.inflation_cost_during_construction.value != 0. + ) + if display_inflation_costs_in_economic_parameters: + # Inflation cost is displayed here for economic models that don't treat inflation cost as a + # capital cost + icc: OutputParameter = econ.inflation_cost_during_construction + icc_label = Outputs._field_label(icc.display_name, 49) + f.write(f' {icc_label}{icc.value:10.2f} {icc.CurrentUnits.value}\n') + f.write(f' Project lifetime: {model.surfaceplant.plant_lifetime.value:10.0f} {model.surfaceplant.plant_lifetime.CurrentUnits.value}\n') f.write(f' Capacity factor: {model.surfaceplant.utilization_factor.value * 100:10.1f} %\n') @@ -497,11 +511,7 @@ def PrintOutputs(self, model: Model): # expenditure. pass - display_inflation_during_construction_in_capital_costs = is_sam_econ_model \ - or (econ.econmodel.value in [EconomicModel.BICYCLE, EconomicModel.FCR, - EconomicModel.STANDARDIZED_LEVELIZED_COST] - and - econ.inflation_cost_during_construction.value != 0.) + display_inflation_during_construction_in_capital_costs = is_sam_econ_model if display_inflation_during_construction_in_capital_costs: icc_label = Outputs._field_label(econ.inflation_cost_during_construction.display_name, 47) f.write(f' {icc_label}{econ.inflation_cost_during_construction.value:10.2f} {econ.inflation_cost_during_construction.CurrentUnits.value}\n') diff --git a/src/geophires_x_client/geophires_x_result.py b/src/geophires_x_client/geophires_x_result.py index c44e3b2f..e2ad9029 100644 --- a/src/geophires_x_client/geophires_x_result.py +++ b/src/geophires_x_client/geophires_x_result.py @@ -79,6 +79,8 @@ class GeophiresXResult: 'Nominal Discount Rate', 'WACC', 'Accrued financing during construction', + # Displayed for economic models that don't treat inflation costs as capital costs (non-SAM-EM) + 'Inflation costs during construction', 'Project lifetime', 'Capacity factor', 'Project NPV', @@ -261,6 +263,7 @@ class GeophiresXResult: 'Total surface equipment costs', 'Exploration costs', 'Investment Tax Credit', + # Displayed for economic models that treat inflation costs as capital costs (SAM-EM) 'Inflation costs during construction', 'Total Add-on CAPEX', 'Total capital costs', diff --git a/src/geophires_x_schema_generator/geophires-result.json b/src/geophires_x_schema_generator/geophires-result.json index 00cab4c7..fa345748 100644 --- a/src/geophires_x_schema_generator/geophires-result.json +++ b/src/geophires_x_schema_generator/geophires-result.json @@ -20,7 +20,7 @@ }, "Total CAPEX": { "type": "number", - "description": "The total capital expenditure (CAPEX) required to construct the plant. This value includes all direct and indirect costs, contingency, and any cost escalation from inflation during construction. It is used as the total installed cost input for SAM Economic Models.", + "description": "The total capital expenditure (CAPEX) required to construct the plant. This value includes all direct and indirect costs, and contingency. For SAM Economic models, it also includes any cost escalation from inflation during construction. It is used as the total installed cost input for SAM Economic Models.", "units": "MUSD" }, "Average Direct-Use Heat Production": {}, @@ -100,6 +100,11 @@ "description": "The accrued inflation on total capital costs over the construction period, as defined by Inflation Rate During Construction. For SAM Economic Models, this is calculated automatically by compounding Inflation Rate over Construction Years if Inflation Rate During Construction is not provided.", "units": "%" }, + "Inflation costs during construction": { + "type": "number", + "description": "The calculated amount of cost escalation due to inflation over the construction period.", + "units": "MUSD" + }, "Project lifetime": {}, "Capacity factor": {}, "Project NPV": { @@ -432,7 +437,7 @@ "Annualized capital costs": {}, "Total CAPEX": { "type": "number", - "description": "The total capital expenditure (CAPEX) required to construct the plant. This value includes all direct and indirect costs, contingency, and any cost escalation from inflation during construction. It is used as the total installed cost input for SAM Economic Models.", + "description": "The total capital expenditure (CAPEX) required to construct the plant. This value includes all direct and indirect costs, and contingency. For SAM Economic models, it also includes any cost escalation from inflation during construction. It is used as the total installed cost input for SAM Economic Models.", "units": "MUSD" }, "Drilling Cost": {}, diff --git a/tests/examples/Fervo_Norbeck_Latimer_2023.out b/tests/examples/Fervo_Norbeck_Latimer_2023.out index 4388a9b7..f8d443af 100644 --- a/tests/examples/Fervo_Norbeck_Latimer_2023.out +++ b/tests/examples/Fervo_Norbeck_Latimer_2023.out @@ -6,8 +6,8 @@ Simulation Metadata ---------------------- GEOPHIRES Version: 3.9.47 Simulation Date: 2025-07-31 - Simulation Time: 08:38 - Calculation Time: 0.476 sec + Simulation Time: 08:57 + Calculation Time: 0.475 sec ***SUMMARY OF RESULTS*** @@ -25,6 +25,7 @@ Simulation Metadata Economic Model = BICYCLE Accrued financing during construction: 5.00 % + Inflation costs during construction: 1.41 MUSD Project lifetime: 10 yr Capacity factor: 90.0 % Project NPV: -13.03 MUSD @@ -103,7 +104,6 @@ Simulation Metadata Field gathering system costs: 1.52 MUSD Total surface equipment costs: 12.85 MUSD Exploration costs: 3.62 MUSD - Inflation costs during construction: 1.41 MUSD Total capital costs: 28.12 MUSD diff --git a/tests/examples/Fervo_Project_Cape-2.out b/tests/examples/Fervo_Project_Cape-2.out index 5c358377..b58acb30 100644 --- a/tests/examples/Fervo_Project_Cape-2.out +++ b/tests/examples/Fervo_Project_Cape-2.out @@ -6,8 +6,8 @@ Simulation Metadata ---------------------- GEOPHIRES Version: 3.9.47 Simulation Date: 2025-07-31 - Simulation Time: 08:38 - Calculation Time: 0.707 sec + Simulation Time: 08:57 + Calculation Time: 0.709 sec ***SUMMARY OF RESULTS*** @@ -25,6 +25,7 @@ Simulation Metadata Economic Model = BICYCLE Accrued financing during construction: 5.00 % + Inflation costs during construction: 2.54 MUSD Project lifetime: 15 yr Capacity factor: 90.0 % Project NPV: 42.34 MUSD @@ -101,7 +102,6 @@ Simulation Metadata Field gathering system costs: 1.68 MUSD Total surface equipment costs: 26.36 MUSD Exploration costs: 0.00 MUSD - Inflation costs during construction: 2.54 MUSD Total capital costs: 50.76 MUSD diff --git a/tests/examples/Fervo_Project_Cape-3.out b/tests/examples/Fervo_Project_Cape-3.out index 93cade9e..1d91ce0e 100644 --- a/tests/examples/Fervo_Project_Cape-3.out +++ b/tests/examples/Fervo_Project_Cape-3.out @@ -6,8 +6,8 @@ Simulation Metadata ---------------------- GEOPHIRES Version: 3.9.47 Simulation Date: 2025-07-31 - Simulation Time: 08:38 - Calculation Time: 0.940 sec + Simulation Time: 08:57 + Calculation Time: 0.951 sec ***SUMMARY OF RESULTS*** @@ -25,6 +25,7 @@ Simulation Metadata Economic Model = BICYCLE Accrued financing during construction: 5.00 % + Inflation costs during construction: 53.65 MUSD Project lifetime: 20 yr Capacity factor: 90.0 % Project NPV: 4580.36 MUSD @@ -102,7 +103,6 @@ Simulation Metadata Total surface equipment costs: 969.26 MUSD Exploration costs: 30.00 MUSD Investment Tax Credit: -459.83 MUSD - Inflation costs during construction: 53.65 MUSD Total capital costs: 1072.95 MUSD diff --git a/tests/examples/Fervo_Project_Cape.out b/tests/examples/Fervo_Project_Cape.out index a4c3747f..ec3f23f1 100644 --- a/tests/examples/Fervo_Project_Cape.out +++ b/tests/examples/Fervo_Project_Cape.out @@ -6,8 +6,8 @@ Simulation Metadata ---------------------- GEOPHIRES Version: 3.9.47 Simulation Date: 2025-07-31 - Simulation Time: 08:38 - Calculation Time: 0.707 sec + Simulation Time: 08:57 + Calculation Time: 0.712 sec ***SUMMARY OF RESULTS*** @@ -25,6 +25,7 @@ Simulation Metadata Economic Model = BICYCLE Accrued financing during construction: 5.00 % + Inflation costs during construction: 24.14 MUSD Project lifetime: 15 yr Capacity factor: 90.0 % Project NPV: 520.01 MUSD @@ -101,7 +102,6 @@ Simulation Metadata Field gathering system costs: 23.00 MUSD Total surface equipment costs: 357.63 MUSD Exploration costs: 0.00 MUSD - Inflation costs during construction: 24.14 MUSD Total capital costs: 482.83 MUSD diff --git a/tests/examples/example10_HP.out b/tests/examples/example10_HP.out index 5107f2db..95394cca 100644 --- a/tests/examples/example10_HP.out +++ b/tests/examples/example10_HP.out @@ -6,7 +6,7 @@ Simulation Metadata ---------------------- GEOPHIRES Version: 3.9.47 Simulation Date: 2025-07-31 - Simulation Time: 08:38 + Simulation Time: 08:57 Calculation Time: 0.105 sec ***SUMMARY OF RESULTS*** @@ -27,6 +27,7 @@ Simulation Metadata Economic Model = Standard Levelized Cost Interest Rate: 5.00 % Accrued financing during construction: 5.00 % + Inflation costs during construction: 1.39 MUSD Project lifetime: 30 yr Capacity factor: 90.0 % Project NPV: 15.18 MUSD @@ -99,7 +100,6 @@ Simulation Metadata Field gathering system costs: 2.55 MUSD Total surface equipment costs: 10.33 MUSD Exploration costs: 3.32 MUSD - Inflation costs during construction: 1.39 MUSD Total capital costs: 27.72 MUSD diff --git a/tests/examples/example11_AC.out b/tests/examples/example11_AC.out index 37915dba..cb655659 100644 --- a/tests/examples/example11_AC.out +++ b/tests/examples/example11_AC.out @@ -6,7 +6,7 @@ Simulation Metadata ---------------------- GEOPHIRES Version: 3.9.47 Simulation Date: 2025-07-31 - Simulation Time: 08:38 + Simulation Time: 08:57 Calculation Time: 0.107 sec ***SUMMARY OF RESULTS*** @@ -28,6 +28,7 @@ Simulation Metadata Economic Model = Standard Levelized Cost Interest Rate: 5.00 % Accrued financing during construction: 5.00 % + Inflation costs during construction: 1.32 MUSD Project lifetime: 30 yr Capacity factor: 90.0 % Project NPV: 10.11 MUSD @@ -100,7 +101,6 @@ Simulation Metadata Field gathering system costs: 2.34 MUSD Total surface equipment costs: 8.96 MUSD Exploration costs: 3.32 MUSD - Inflation costs during construction: 1.32 MUSD Total capital costs: 26.35 MUSD diff --git a/tests/examples/example3.out b/tests/examples/example3.out index b0f5a3c8..9d4c402a 100644 --- a/tests/examples/example3.out +++ b/tests/examples/example3.out @@ -6,8 +6,8 @@ Simulation Metadata ---------------------- GEOPHIRES Version: 3.9.47 Simulation Date: 2025-07-31 - Simulation Time: 08:38 - Calculation Time: 0.123 sec + Simulation Time: 08:57 + Calculation Time: 0.124 sec ***SUMMARY OF RESULTS*** @@ -27,6 +27,7 @@ Simulation Metadata Economic Model = BICYCLE Accrued financing during construction: 5.00 % + Inflation costs during construction: 5.18 MUSD Project lifetime: 35 yr Capacity factor: 90.0 % Project NPV: -2.38 MUSD @@ -97,7 +98,6 @@ Simulation Metadata Field gathering system costs: 3.17 MUSD Total surface equipment costs: 67.22 MUSD Exploration costs: 4.64 MUSD - Inflation costs during construction: 5.18 MUSD Total capital costs: 103.68 MUSD From 20931d635318c7a1a38cf484fc0b97046b7abf86 Mon Sep 17 00:00:00 2001 From: softwareengineerprogrammer <4056124+softwareengineerprogrammer@users.noreply.github.com> Date: Thu, 31 Jul 2025 12:11:36 -0700 Subject: [PATCH 5/6] py38 compatibility - test_production_well_stimulation_cost/test_geophires_x.py --- tests/test_geophires_x.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/test_geophires_x.py b/tests/test_geophires_x.py index 1e2c5607..0ac9abf1 100644 --- a/tests/test_geophires_x.py +++ b/tests/test_geophires_x.py @@ -1,10 +1,11 @@ +from __future__ import annotations + import math import os import tempfile import uuid from pathlib import Path from typing import Any -from typing import Optional from geophires_x.OptionList import PlantType from geophires_x.OptionList import WellDrillingCostCorrelation @@ -270,7 +271,7 @@ def _sanitize_nan(self, r: GeophiresXResult) -> None: except TypeError: pass - def _get_unequal_dicts_approximate_percent_difference(self, d1: dict, d2: dict) -> Optional[float]: + def _get_unequal_dicts_approximate_percent_difference(self, d1: dict, d2: dict) -> float | None: for i in range(99): try: self.assertDictAlmostEqual(d1, d2, percent=i) @@ -967,9 +968,9 @@ def test_sbt_coaxial_raises_error(self): def test_production_well_stimulation_cost(self): def _get_result( - prod_well_stim_MUSD: Optional[int] = None, - inj_well_stim_MUSD: Optional[int] = None, - additional_params: Optional[dict[str, Any]] = None, + prod_well_stim_MUSD: int | None = None, + inj_well_stim_MUSD: int | None = None, + additional_params: dict[str, Any] | None = None, ) -> GeophiresXResult: if additional_params is None: additional_params = {} @@ -1030,9 +1031,9 @@ def _get_result( def test_indirect_costs(self): def _get_result( - indirect_cost_percent: Optional[int] = None, - stimulation_indirect_cost_percent: Optional[int] = None, - wellfield_indirect_cost_percent: Optional[int] = None, + indirect_cost_percent: int | None = None, + stimulation_indirect_cost_percent: int | None = None, + wellfield_indirect_cost_percent: int | None = None, input_file_path: str = 'geophires_x_tests/generic-egs-case.txt', ) -> float: p = {} @@ -1130,7 +1131,7 @@ def wellfield_cost(result_cap_costs): def test_contingency(self): def _get_result( - contingency_percentage: Optional[int] = None, + contingency_percentage: int | None = None, input_file_path: str = 'geophires_x_tests/generic-egs-case.txt', ) -> float: p = {} From 023a7f069cd7174121f00841d48dd99578e438f0 Mon Sep 17 00:00:00 2001 From: softwareengineerprogrammer <4056124+softwareengineerprogrammer@users.noreply.github.com> Date: Fri, 1 Aug 2025 07:45:17 -0700 Subject: [PATCH 6/6] Address unit conversion TODO --- src/geophires_x/Economics.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/geophires_x/Economics.py b/src/geophires_x/Economics.py index 181a1677..b89cb1fa 100644 --- a/src/geophires_x/Economics.py +++ b/src/geophires_x/Economics.py @@ -369,20 +369,23 @@ def CalculateLCOELCOHLCOC(econ, model: Model) -> tuple[float, float, float]: Coam_heat = (econ.Coam.value * (1.0 - econ.CAPEX_heat_electricity_plant_ratio.value)) def _capex_total_plus_construction_inflation() -> float: - # TODO unit conversions # TODO should be return value instead of mutating econ - econ.inflation_cost_during_construction.value = econ.CCap.value * econ.inflrateconstruction.value + econ.inflation_cost_during_construction.value = quantity( + econ.CCap.value * econ.inflrateconstruction.value, + econ.CCap.CurrentUnits + ).to(econ.inflation_cost_during_construction.CurrentUnits).magnitude return econ.CCap.value + econ.inflation_cost_during_construction.value def _construction_inflation_cost_elec_heat() -> tuple[float, float]: - # TODO unit conversions construction_inflation_cost_elec = CCap_elec * econ.inflrateconstruction.value construction_inflation_cost_heat = CCap_heat * econ.inflrateconstruction.value # TODO should be return value instead of mutating econ - econ.inflation_cost_during_construction.value = (construction_inflation_cost_elec - + construction_inflation_cost_heat) + econ.inflation_cost_during_construction.value = quantity( + construction_inflation_cost_elec+ construction_inflation_cost_heat, + econ.CCap.CurrentUnits + ).to(econ.inflation_cost_during_construction.CurrentUnits).magnitude return CCap_elec + construction_inflation_cost_elec, CCap_heat + construction_inflation_cost_heat