From 10694bf6b1000a730ff9d378301aab60a2bf8a3e Mon Sep 17 00:00:00 2001 From: Malcolm Ross Date: Tue, 9 Jan 2024 18:06:05 -0600 Subject: [PATCH] Objectifying surfaceplant. recoding NC_GEOPHIRES to create PDF graph and output it a PNG. --- docs/reference/geophires_x.rst | 4 +- src/geophires_x/AGSEconomics.py | 14 +- src/geophires_x/AGSWellBores.py | 13 +- src/geophires_x/Economics.py | 153 +++++++-------- src/geophires_x/EconomicsCCUS.py | 7 +- src/geophires_x/MC_GeoPHIRES3.py | 1 + src/geophires_x/Model.py | 154 +++++++-------- src/geophires_x/Outputs.py | 39 ++-- src/geophires_x/OutputsAddOns.py | 3 +- src/geophires_x/OutputsCCUS.py | 3 +- src/geophires_x/OutputsS_DAC_GT.py | 3 +- src/geophires_x/Reservoir.py | 2 +- src/geophires_x/SurfacePlant.py | 34 ++-- ...{AGSSurfacePlant.py => SurfacePlantAGS.py} | 176 ++++++++---------- .../SurfacePlantAbsorptionChiller.py | 6 +- .../SurfacePlantDistrictHeating.py | 16 +- src/geophires_x/SurfacePlantDoubleFlash.py | 2 +- src/geophires_x/SurfacePlantHeatPump.py | 6 +- ...eHeat.py => SurfacePlantIndustrialHeat.py} | 4 +- src/geophires_x/SurfacePlantSUTRA.py | 15 +- src/geophires_x/SurfacePlantSingleFlash.py | 2 +- src/geophires_x/SurfacePlantSubcriticalORC.py | 4 +- .../SurfacePlantSupercriticalORC.py | 2 +- src/geophires_x/WellBores.py | 54 +++--- src/geophires_x_schema_generator/__init__.py | 8 +- 25 files changed, 312 insertions(+), 413 deletions(-) rename src/geophires_x/{AGSSurfacePlant.py => SurfacePlantAGS.py} (86%) rename src/geophires_x/{SurfacePlantDirectUseHeat.py => SurfacePlantIndustrialHeat.py} (98%) diff --git a/docs/reference/geophires_x.rst b/docs/reference/geophires_x.rst index 16329672..920c48c8 100644 --- a/docs/reference/geophires_x.rst +++ b/docs/reference/geophires_x.rst @@ -31,10 +31,10 @@ geophires_x .. automodule:: geophires_x.SurfacePlant :members: -.. automodule:: geophires_x.AGSSurfacePlant +.. automodule:: geophires_x.SurfacePlantAGS :members: -.. automodule:: geophires_x.SUTRASurfacePlant +.. automodule:: geophires_x.SurfacePlantSUTRA :members: .. automodule:: geophires_x.Economics diff --git a/src/geophires_x/AGSEconomics.py b/src/geophires_x/AGSEconomics.py index 9b7e0a7e..20b271cd 100644 --- a/src/geophires_x/AGSEconomics.py +++ b/src/geophires_x/AGSEconomics.py @@ -171,7 +171,7 @@ def verify(self, model: Model) -> int: "Error: CLGS model database imposes additional range restrictions: Power plant capital cost must be \ between 0 and 10,000 $/kWe. Simulation terminated.") self.error = 1 - if model.surfaceplant.End_use not in (EndUseOptions.HEAT, EndUseOptions.ELECTRICITY): + if model.surfaceplant.enduse_option.value not in (EndUseOptions.HEAT, EndUseOptions.ELECTRICITY): print( "Error: CLGS model database imposes additional range restrictions: Economic Calculations can only be \ made only for electricity or heat, not a combination.") @@ -204,10 +204,10 @@ def Calculate(self, model: Model) -> None: vertical_CAPEX_Drilling = vert * self.Vertical_drilling_cost_per_m.value / 1e6 # Drilling capital cost [M$] horizontal_CAPEX_Drilling = horiz * self.Nonvertical_drilling_cost_per_m.value / 1e6 # Drilling capital cost [M$] self.CAPEX_Drilling = vertical_CAPEX_Drilling + horizontal_CAPEX_Drilling - if model.surfaceplant.End_use == EndUseOptions.HEAT: + if model.surfaceplant.enduse_option.value == EndUseOptions.HEAT: self.CAPEX_Surface_Plant = np.max( model.surfaceplant.Instantaneous_heat_production) * self.Direct_use_heat_cost_per_kWth.value / 1e6 # [M$] - elif model.surfaceplant.End_use == EndUseOptions.ELECTRICITY: + elif model.surfaceplant.enduse_option.value == EndUseOptions.ELECTRICITY: if model.wellbores.Fluid.value == WorkingFluid.WATER: self.CAPEX_Surface_Plant = np.max( model.surfaceplant.Instantaneous_electricity_production_method_1) * self.Power_plant_cost_per_kWe.value / 1e6 # [M$] @@ -218,9 +218,9 @@ def Calculate(self, model: Model) -> None: self.TotalCAPEX = self.CAPEX_Drilling + self.CAPEX_Surface_Plant # Total system capital cost (only includes drilling and surface plant cost) [M$] # Calculate OPEX - if model.surfaceplant.End_use == EndUseOptions.HEAT: + if model.surfaceplant.enduse_option.value == EndUseOptions.HEAT: self.OPEX_Plant = self.O_and_M_cost_plant.value * self.CAPEX_Surface_Plant + model.surfaceplant.Annual_pumping_power * self.Electricity_rate / 1e6 # Annual plant O&M cost [M$/year] - elif model.surfaceplant.End_use == EndUseOptions.ELECTRICITY: + elif model.surfaceplant.enduse_option.value == EndUseOptions.ELECTRICITY: self.OPEX_Plant = self.O_and_M_cost_plant.value * self.CAPEX_Surface_Plant # Annual plant O&M cost [M$/year] self.AverageOPEX_Plant = np.average(self.OPEX_Plant) @@ -228,14 +228,14 @@ def Calculate(self, model: Model) -> None: # Calculate LCO(H)(E) Discount_vector = 1. / np.power(1 + self.Discount_rate, np.linspace(0, model.surfaceplant.Lifetime - 1, model.surfaceplant.Lifetime)) - if model.surfaceplant.End_use == EndUseOptions.HEAT: + if model.surfaceplant.enduse_option.value == EndUseOptions.HEAT: self.LCOH.CurrentUnits = EnergyCostUnit.DOLLARSPERMWH self.LCOH.value = (self.TotalCAPEX + np.sum(self.OPEX_Plant * Discount_vector)) * 1e6 / np.sum( model.surfaceplant.Annual_heat_production / 1e3 * Discount_vector) # $/MWh if self.LCOH.value < 0: self.LCOH.value = 9999 model.surfaceplant.error_codes = np.append(model.surfaceplant.error_codes, 5000) - elif model.surfaceplant.End_use == EndUseOptions.ELECTRICITY: + elif model.surfaceplant.enduse_option.value == EndUseOptions.ELECTRICITY: self.LCOE.CurrentUnits = EnergyCostUnit.DOLLARSPERMWH if model.surfaceplant.Average_electricity_production == 0: self.LCOE.value = 9999 diff --git a/src/geophires_x/AGSWellBores.py b/src/geophires_x/AGSWellBores.py index 252665fe..031b1b91 100644 --- a/src/geophires_x/AGSWellBores.py +++ b/src/geophires_x/AGSWellBores.py @@ -77,7 +77,7 @@ def __init__(self, fname, case, fluid): # dim = Mdot x L2 x L1 x grad x D x Tinj x k self.Wt = file[output_loc + "Wt"][:] # int mdot * dh dt - self.We = file[output_loc + "reservoir_producible_electricity"][:] # int mdot * (dh - Too * ds) dt + self.We = file[output_loc + "We"][:] # int mdot * (dh - Too * ds) dt self.GWhr = 1e6 * 3_600_000.0 @@ -657,14 +657,19 @@ def read_parameters(self, model: Model) -> None: key = ParameterToModify.Name.strip() if key in model.InputParameters: ParameterReadIn = model.InputParameters[key] - # just handle special cases for this class - the call to super set all thr values, + # just handle special cases for this class - the call to super set all the values, # including the value unique to this class - if ParameterToModify.Name == "Heat Transfer Fluid": + if ParameterToModify.Name == "Multilaterals Cased": + if ParameterReadIn.sValue == str(1): + self.NonverticalsCased.value = True + else: + self.NonverticalsCased.value = False + elif ParameterToModify.Name == "Heat Transfer Fluid": if ParameterReadIn.sValue == str(1): self.Fluid.value = WorkingFluid.WATER else: self.Fluid.value = WorkingFluid.SCO2 - if ParameterToModify.Name == "Closed-loop Configuration": + elif ParameterToModify.Name == "Closed-loop Configuration": if ParameterReadIn.sValue == str(1): self.Configuration.value = Configuration.ULOOP else: diff --git a/src/geophires_x/Economics.py b/src/geophires_x/Economics.py index 2ef8889d..6d09f936 100644 --- a/src/geophires_x/Economics.py +++ b/src/geophires_x/Economics.py @@ -136,7 +136,8 @@ def CalculateLCOELCOH(self, model: Model) -> tuple: if model.surfaceplant.enduse_option.value == EndUseOptions.ELECTRICITY: LCOE = (self.FCR.value * (1 + self.inflrateconstruction.value) * self.CCap.value + self.Coam.value) / \ np.average(model.surfaceplant.NetkWhProduced.value) * 1E8 # cents/kWh - elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT: + 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 = (self.FCR.value * (1 + self.inflrateconstruction.value) * self.CCap.value + self.Coam.value + self.averageannualpumpingcosts.value) / np.average( model.surfaceplant.HeatkWhProduced.value) * 1E8 # cents/kWh @@ -164,17 +165,17 @@ def CalculateLCOELCOH(self, model: Model) -> tuple: LCOH = (self.CCap.value + self.Coam.value - averageannualelectricityincome) / np.average( model.surfaceplant.HeatkWhProduced.value) * 1E8 # cents/kWh LCOH = LCOH * 2.931 # $/MMBTU - elif model.surfaceplant.plant_type.value == PlantType.ABSORPTION_CHILLER: + elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value == PlantType.ABSORPTION_CHILLER: LCOC = (self.FCR.value * ( 1 + self.inflrateconstruction.value) * self.CCap.value + self.Coam.value + self.averageannualpumpingcosts.value) / np.average( model.surfaceplant.cooling_kWh_Produced.value) * 1E8 # cents/kWh LCOC = LCOC * 2.931 # $/Million Btu - elif model.surfaceplant.plant_type.value == PlantType.HEAT_PUMP: + elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value == PlantType.HEAT_PUMP: LCOH = (self.FCR.value * ( 1 + self.inflrateconstruction.value) * self.CCap.value + self.Coam.value + self.averageannualpumpingcosts.value + self.averageannualheatpumpelectricitycost.value) / np.average( model.surfaceplant.HeatkWhProduced.value) * 1E8 # cents/kWh LCOH = LCOH * 2.931 # $/Million Btu - elif model.surfaceplant.plant_type.value == PlantType.DISTRICT_HEATING: + elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value == PlantType.DISTRICT_HEATING: LCOH = (self.FCR.value * ( 1 + self.inflrateconstruction.value) * self.CCap.value + self.Coam.value + self.averageannualpumpingcosts.value + self.averageannualngcost.value) / model.surfaceplant.annual_heating_demand.value * 1E2 # cents/kWh LCOH = LCOH * 2.931 # $/Million Btu @@ -186,7 +187,8 @@ def CalculateLCOELCOH(self, model: Model) -> tuple: LCOE = ((1 + self.inflrateconstruction.value) * self.CCap.value + np.sum( self.Coam.value * discountvector)) / np.sum( model.surfaceplant.NetkWhProduced.value * discountvector) * 1E8 # cents/kWh - elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT: + 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]: self.averageannualpumpingcosts.value = np.average( model.surfaceplant.PumpingkWh.value) * model.surfaceplant.electricity_cost_to_buy.value / 1E6 # M$/year LCOH = ((1 + self.inflrateconstruction.value) * self.CCap.value + np.sum(( @@ -215,20 +217,20 @@ def CalculateLCOELCOH(self, model: Model) -> tuple: model.surfaceplant.HeatkWhProduced.value * discountvector) * 1E8 # cents/kWh LCOH = LCOH * 2.931 # $/MMBTU - elif model.surfaceplant.plant_type.value == PlantType.ABSORPTION_CHILLER: + elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value == PlantType.ABSORPTION_CHILLER: LCOC = ((1 + self.inflrateconstruction.value) * self.CCap.value + np.sum(( self.Coam.value + model.surfaceplant.PumpingkWh.value * model.surfaceplant.electricity_cost_to_buy.value / 1E6) * discountvector)) / np.sum( model.surfaceplant.cooling_kWh_Produced.value * discountvector) * 1E8 # cents/kWh LCOC = LCOC * 2.931 # $/Million Btu - elif model.surfaceplant.plant_type.value == PlantType.HEAT_PUMP: + elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value == PlantType.HEAT_PUMP: LCOH = ((1 + self.inflrateconstruction.value) * self.CCap.value + np.sum( - (self.Coam.value + model.surfaceplant.PumpingkWh.value * model.surfaceplant.electricity_cost_to_buy.value / 1E6 + \ + (self.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) * discountvector)) / np.sum( model.surfaceplant.HeatkWhProduced.value * discountvector) * 1E8 # cents/kWh LCOH = LCOH * 2.931 # $/Million Btu - elif model.surfaceplant.plant_type.value == PlantType.DISTRICT_HEATING: + elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value == PlantType.DISTRICT_HEATING: LCOH = ((1 + self.inflrateconstruction.value) * self.CCap.value + np.sum( - (self.Coam.value + model.surfaceplant.PumpingkWh.value * model.surfaceplant.electricity_cost_to_buy.value / 1E6 + \ + (self.Coam.value + model.surfaceplant.PumpingkWh.value * model.surfaceplant.electricity_cost_to_buy.value / 1E6 + self.annualngcost.value) * discountvector)) / np.sum( model.surfaceplant.annual_heating_demand.value * discountvector) * 1E2 # cents/kWh LCOH = LCOH * 2.931 # $/Million Btu @@ -252,7 +254,8 @@ def CalculateLCOELCOH(self, model: Model) -> tuple: NPVgrt = self.GTR.value / (1 - self.GTR.value) * (NPVcap + NPVoandm + NPVfc + NPVit - NPVitc) LCOE = (NPVcap + NPVoandm + NPVfc + NPVit + NPVgrt - NPVitc) / np.sum( model.surfaceplant.NetkWhProduced.value * inflationvector * discountvector) * 1E8 - elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT: + 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]: PumpingCosts = model.surfaceplant.PumpingkWh.value * model.surfaceplant.electricity_cost_to_buy.value / 1E6 NPVoandm = np.sum((self.Coam.value + PumpingCosts) * inflationvector * discountvector) NPVgrt = self.GTR.value / (1 - self.GTR.value) * (NPVcap + NPVoandm + NPVfc + NPVit - NPVitc) @@ -285,7 +288,7 @@ def CalculateLCOELCOH(self, model: Model) -> tuple: model.surfaceplant.HeatkWhProduced.value * inflationvector * discountvector) * 1E8 LCOH = self.LCOELCOHCombined.value * 2.931 # $/MMBTU - elif model.surfaceplant.plant_type.value == PlantType.ABSORPTION_CHILLER: + elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value == PlantType.ABSORPTION_CHILLER: PumpingCosts = model.surfaceplant.PumpingkWh.value * model.surfaceplant.electricity_cost_to_buy.value / 1E6 NPVoandm = np.sum((self.Coam.value + PumpingCosts) * inflationvector * discountvector) NPVgrt = self.GTR.value / (1 - self.GTR.value) * (NPVcap + NPVoandm + NPVfc + NPVit - NPVitc) @@ -293,7 +296,7 @@ def CalculateLCOELCOH(self, model: Model) -> tuple: model.surfaceplant.cooling_kWh_Produced.value * inflationvector * discountvector) * 1E8 LCOC = LCOC * 2.931 # $/MMBTU - elif model.surfaceplant.plant_type.value == PlantType.HEAT_PUMP: + elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value == PlantType.HEAT_PUMP: PumpingCosts = model.surfaceplant.PumpingkWh.value * model.surfaceplant.electricity_cost_to_buy.value / 1E6 HeatPumpElecCosts = model.surfaceplant.heat_pump_electricity_kwh_used.value * model.surfaceplant.electricity_cost_to_buy.value / 1E6 NPVoandm = np.sum((self.Coam.value + PumpingCosts + HeatPumpElecCosts) * inflationvector * discountvector) @@ -302,7 +305,7 @@ def CalculateLCOELCOH(self, model: Model) -> tuple: model.surfaceplant.HeatkWhProduced.value * inflationvector * discountvector) * 1E8 LCOH = self.LCOH.value * 2.931 # $/MMBTU - elif model.surfaceplant.plant_type.value == PlantType.DISTRICT_HEATING: + elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value == PlantType.DISTRICT_HEATING: PumpingCosts = model.surfaceplant.PumpingkWh.value * model.surfaceplant.electricity_cost_to_buy.value / 1E6 NPVoandm = np.sum( (self.Coam.value + PumpingCosts + self.annualngcost.value) * inflationvector * discountvector) @@ -962,29 +965,6 @@ def __init__(self, model: Model): ToolTipText="Specify the population in the district heating network" ) - self.ElecPrice = self.OutputParameterDict[self.ElecPrice.Name] = OutputParameter( - "Electricity Sale Price Model", - value=[0.055], - UnitType=Units.ENERGYCOST, - PreferredUnits=EnergyCostUnit.CENTSSPERKWH, - CurrentUnits=EnergyCostUnit.CENTSSPERKWH - ) - self.HeatPrice = self.OutputParameterDict[self.HeatPrice.Name] = OutputParameter( - "Heat Sale Price Model", - value=[0.025], - UnitType=Units.ENERGYCOST, - PreferredUnits=EnergyCostUnit.CENTSSPERKWH, - CurrentUnits=EnergyCostUnit.CENTSSPERKWH - ) - - self.LCOC = self.OutputParameterDict[self.LCOC.Name] = OutputParameter( - Name="LCOC", - value=0.0, - UnitType=Units.ENERGYCOST, - PreferredUnits=EnergyCostUnit.DOLLARSPERMMBTU, - CurrentUnits=EnergyCostUnit.DOLLARSPERMMBTU - ) - self.HeatStartPrice = self.ParameterDict[self.HeatStartPrice.Name] = floatParameter( "Starting Heat Sale Price", value=0.025, @@ -1144,101 +1124,108 @@ def __init__(self, model: Model): self.MyPath = os.path.abspath(__file__) # results + self.ElecPrice = self.OutputParameterDict[self.ElecPrice.Name] = OutputParameter( + "Electricity Sale Price Model", + UnitType=Units.ENERGYCOST, + PreferredUnits=EnergyCostUnit.CENTSSPERKWH, + CurrentUnits=EnergyCostUnit.CENTSSPERKWH + ) + self.HeatPrice = self.OutputParameterDict[self.HeatPrice.Name] = OutputParameter( + "Heat Sale Price Model", + UnitType=Units.ENERGYCOST, + PreferredUnits=EnergyCostUnit.CENTSSPERKWH, + CurrentUnits=EnergyCostUnit.CENTSSPERKWH + ) + + self.LCOC = self.OutputParameterDict[self.LCOC.Name] = OutputParameter( + Name="LCOC", + UnitType=Units.ENERGYCOST, + PreferredUnits=EnergyCostUnit.DOLLARSPERMMBTU, + CurrentUnits=EnergyCostUnit.DOLLARSPERMMBTU + ) + self.LCOE = self.OutputParameterDict[self.LCOE.Name] = OutputParameter( Name="LCOE", - value=0.0, UnitType=Units.ENERGYCOST, PreferredUnits=EnergyCostUnit.CENTSSPERKWH, CurrentUnits=EnergyCostUnit.CENTSSPERKWH ) self.LCOH = self.OutputParameterDict[self.LCOH.Name] = OutputParameter( Name="LCOH", - value=0.0, UnitType=Units.ENERGYCOST, PreferredUnits=EnergyCostUnit.DOLLARSPERMMBTU, CurrentUnits=EnergyCostUnit.DOLLARSPERMMBTU ) # $/MMBTU self.Cstim = self.OutputParameterDict[self.Cstim.Name] = OutputParameter( Name="O&M Surface Plant costs", - value=-999.9, UnitType=Units.CURRENCY, PreferredUnits=CurrencyUnit.MDOLLARS, CurrentUnits=CurrencyUnit.MDOLLARS ) self.Cexpl = self.OutputParameterDict[self.Cexpl.Name] = OutputParameter( Name="Exploration cost", - value=-999.9, UnitType=Units.CURRENCY, PreferredUnits=CurrencyUnit.MDOLLARS, CurrentUnits=CurrencyUnit.MDOLLARS ) self.Cwell = self.OutputParameterDict[self.Cwell.Name] = OutputParameter( Name="Wellfield cost", - value=-999.9, UnitType=Units.CURRENCY, PreferredUnits=CurrencyUnit.MDOLLARS, CurrentUnits=CurrencyUnit.MDOLLARS ) self.Coamwell = self.OutputParameterDict[self.Coamwell.Name] = OutputParameter( Name="O&M Wellfield cost", - value=-999.9, UnitType=Units.CURRENCYFREQUENCY, PreferredUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR, CurrentUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR ) self.Cplant = self.OutputParameterDict[self.Cplant.Name] = OutputParameter( Name="Surface Plant cost", - value=-999.9, UnitType=Units.CURRENCY, PreferredUnits=CurrencyUnit.MDOLLARS, CurrentUnits=CurrencyUnit.MDOLLARS ) self.Coamplant = self.OutputParameterDict[self.Coamplant.Name] = OutputParameter( Name="O&M Surface Plant costs", - value=-999.9, UnitType=Units.CURRENCYFREQUENCY, PreferredUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR, CurrentUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR ) self.Cgath = self.OutputParameterDict[self.Cgath.Name] = OutputParameter( Name="Field gathering system cost", - value=-999.9, UnitType=Units.CURRENCY, PreferredUnits=CurrencyUnit.MDOLLARS, CurrentUnits=CurrencyUnit.MDOLLARS ) self.Cpiping = self.OutputParameterDict[self.Cpiping.Name] = OutputParameter( Name="Transmission pipeline costs", - value=-999.9, UnitType=Units.CURRENCY, PreferredUnits=CurrencyUnit.MDOLLARS, CurrentUnits=CurrencyUnit.MDOLLARS ) self.Coamwater = self.OutputParameterDict[self.Coamwater.Name] = OutputParameter( Name="O&M Make-up Water costs", - value=-999.9, UnitType=Units.CURRENCYFREQUENCY, PreferredUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR, CurrentUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR ) self.CCap = self.OutputParameterDict[self.CCap.Name] = OutputParameter( Name="Total Capital Cost", - value=-999.9, UnitType=Units.CURRENCY, PreferredUnits=CurrencyUnit.MDOLLARS, CurrentUnits=CurrencyUnit.MDOLLARS ) self.Coam = self.OutputParameterDict[self.Coam.Name] = OutputParameter( Name="Total O&M Cost", - value=-999.9, UnitType=Units.CURRENCYFREQUENCY, PreferredUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR, CurrentUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR ) - self.averageannualpumpingcosts = self.OutputParameterDict[ - self.averageannualpumpingcosts.Name] = OutputParameter( +# self.averageannualpumpingcosts = self.OutputParameterDict[ +# self.averageannualpumpingcosts.Name] = OutputParameter( #typo here!??! + self.averageannualpumpingcosts = OutputParameter( Name="Average Annual Pumping Costs", - value=-0.0, UnitType=Units.CURRENCYFREQUENCY, PreferredUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR, CurrentUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR @@ -1248,7 +1235,6 @@ def __init__(self, model: Model): self.averageannualheatpumpelectricitycost = self.OutputParameterDict[ self.averageannualheatpumpelectricitycost.Name] = OutputParameter( Name="Average Annual Heat Pump Electricity Cost", - value=0.0, UnitType=Units.CURRENCYFREQUENCY, PreferredUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR, CurrentUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR @@ -1257,41 +1243,36 @@ def __init__(self, model: Model): # district heating self.peakingboilercost = self.OutputParameterDict[self.peakingboilercost.Name] = OutputParameter( Name="Peaking boiler cost", - value=0, UnitType=Units.CURRENCY, PreferredUnits=CurrencyUnit.MDOLLARS, CurrentUnits=CurrencyUnit.MDOLLARS ) self.dhdistrictcost = self.OutputParameterDict[self.dhdistrictcost.Name] = OutputParameter( Name="District Heating System Cost", - value=0, UnitType=Units.CURRENCY, PreferredUnits=CurrencyUnit.MDOLLARS, CurrentUnits=CurrencyUnit.MDOLLARS ) self.populationdensity = self.OutputParameterDict[self.populationdensity.Name] = OutputParameter( Name="District Heating System Population Density", - value=0, UnitType=Units.POPDENSITY, PreferredUnits=PopDensityUnit.perkm2, CurrentUnits=PopDensityUnit.perkm2 ) self.annualngcost = self.OutputParameterDict[self.annualngcost.Name] = OutputParameter( Name="Annual Peaking Fuel Cost", - value=0, UnitType=Units.CURRENCYFREQUENCY, + UnitType=Units.CURRENCYFREQUENCY, PreferredUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR, CurrentUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR ) self.dhdistrictoandmcost = self.OutputParameterDict[self.dhdistrictoandmcost.Name] = OutputParameter( Name="Annual District Heating O&M Cost", - value=0, UnitType=Units.CURRENCYFREQUENCY, PreferredUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR, CurrentUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR ) self.averageannualngcost = self.OutputParameterDict[self.averageannualngcost.Name] = OutputParameter( Name="Average Annual Peaking Fuel Cost", - value=0, UnitType=Units.CURRENCYFREQUENCY, PreferredUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR, CurrentUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR @@ -1299,70 +1280,60 @@ def __init__(self, model: Model): self.ElecRevenue = self.OutputParameterDict[self.ElecRevenue.Name] = OutputParameter( Name="Annual Revenue from Electricity Production", - value=[0.0], UnitType=Units.CURRENCYFREQUENCY, PreferredUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR, CurrentUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR ) self.ElecCummRevenue = self.OutputParameterDict[self.ElecCummRevenue.Name] = OutputParameter( Name="Cumulative Revenue from Electricity Production", - value=[0.0], UnitType=Units.CURRENCY, PreferredUnits=CurrencyUnit.MDOLLARS, CurrentUnits=CurrencyUnit.MDOLLARS ) self.HeatRevenue = self.OutputParameterDict[self.HeatRevenue.Name] = OutputParameter( Name="Annual Revenue from Heat Production", - value=[0.0], UnitType=Units.CURRENCYFREQUENCY, PreferredUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR, CurrentUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR ) self.HeatCummRevenue = self.OutputParameterDict[self.HeatCummRevenue.Name] = OutputParameter( Name="Cumulative Revenue from Electricity Production", - value=[0.0], UnitType=Units.CURRENCY, PreferredUnits=CurrencyUnit.MDOLLARS, CurrentUnits=CurrencyUnit.MDOLLARS ) self.TotalRevenue = self.OutputParameterDict[self.TotalRevenue.Name] = OutputParameter( Name="Annual Revenue from Project", - value=[0.0], UnitType=Units.CURRENCYFREQUENCY, PreferredUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR, CurrentUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR ) self.TotalCummRevenue = self.OutputParameterDict[self.TotalCummRevenue.Name] = OutputParameter( Name="Cumulative Revenue from Project", - value=[0.0], UnitType=Units.CURRENCY, PreferredUnits=CurrencyUnit.MDOLLARS, CurrentUnits=CurrencyUnit.MDOLLARS ) self.ProjectNPV = self.OutputParameterDict[self.ProjectNPV.Name] = OutputParameter( "Project Net Present Value", - value=0.0, UnitType=Units.CURRENCY, PreferredUnits=CurrencyUnit.MDOLLARS, CurrentUnits=CurrencyUnit.MDOLLARS ) self.ProjectIRR = self.OutputParameterDict[self.ProjectIRR.Name] = OutputParameter( "Project Internal Rate of Return", - value=0.0, UnitType=Units.PERCENT, PreferredUnits=PercentUnit.PERCENT, CurrentUnits=PercentUnit.PERCENT ) self.ProjectVIR = self.OutputParameterDict[self.ProjectVIR.Name] = OutputParameter( "Project Value Investment Ratio", - value=0.0, UnitType=Units.PERCENT, PreferredUnits=PercentUnit.TENTH, CurrentUnits=PercentUnit.TENTH ) self.ProjectMOIC = self.OutputParameterDict[self.ProjectMOIC.Name] = OutputParameter( "Project Multiple of Invested Capital", - value=0.0, UnitType=Units.PERCENT, PreferredUnits=PercentUnit.TENTH, CurrentUnits=PercentUnit.TENTH @@ -1402,7 +1373,22 @@ def read_parameters(self, model: Model) -> None: ReadParameter(ParameterReadIn, ParameterToModify, model) # handle special cases - if ParameterToModify.Name == "Economic Model": + if ParameterToModify.Name == "Do AddOn Calculations": + if ParameterReadIn.sValue == '1': + self.DoAddOnCalculations.value = True + else: + self.DoAddOnCalculations.value = False + elif ParameterToModify.Name == "Do CCUS Calculations": + if ParameterReadIn.sValue == '1': + self.DoCCUSCalculations.value = True + else: + self.DoCCUSCalculations.value = False + elif ParameterToModify.Name == "Do S-DAC-GT Calculations": + if ParameterReadIn.sValue == '1': + self.DoSDACGTCalculations.value = True + else: + self.DoSDACGTCalculations.value = False + elif ParameterToModify.Name == "Economic Model": if ParameterReadIn.sValue == '1': self.econmodel.value = EconomicModel.FCR elif ParameterReadIn.sValue == '2': @@ -1876,7 +1862,8 @@ def Calculate(self, model: Model) -> None: (model.wellbores.nprod.value + model.wellbores.ninj.value) * 750 * 500. + self.Cpumps) / 1E6 # plant costs - if model.surfaceplant.enduse_option.value == EndUseOptions.HEAT: # direct-use + if (model.surfaceplant.enduse_option.value == EndUseOptions.HEAT + and model.surfaceplant.plant_type.value not in [PlantType.ABSORPTION_CHILLER, PlantType.HEAT_PUMP, PlantType.DISTRICT_HEATING]): # direct-use if self.ccplantfixed.Valid: self.Cplant.value = self.ccplantfixed.value else: @@ -1884,7 +1871,7 @@ def Calculate(self, model: Model) -> None: model.surfaceplant.HeatExtracted.value) * 1000. # 1.15 for 15% contingency and 1.12 for 12% indirect costs # absorption chiller - elif model.surfaceplant.enduse_option.value == PlantType.ABSORPTION_CHILLER: # absorption chiller + elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value == PlantType.ABSORPTION_CHILLER: # absorption chiller if self.ccplantfixed.Valid: self.Cplant.value = self.ccplantfixed.value else: @@ -1899,7 +1886,7 @@ def Calculate(self, model: Model) -> None: self.Cplant.value += self.chillercapex.value # heat pump - elif model.surfaceplant.enduse_option.value == PlantType.HEAT_PUMP: + elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value == PlantType.HEAT_PUMP: if self.ccplantfixed.Valid: self.Cplant.value = self.ccplantfixed.value else: @@ -1914,7 +1901,7 @@ def Calculate(self, model: Model) -> None: self.Cplant.value += self.heatpumpcapex.value # district heating - elif model.surfaceplant.enduse_option.value == PlantType.DISTRICT_HEATING: + elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value == PlantType.DISTRICT_HEATING: if self.ccplantfixed.Valid: self.Cplant.value = self.ccplantfixed.value else: @@ -2099,7 +2086,7 @@ def Calculate(self, model: Model) -> None: self.Cpiping.value = 750 / 1000 * model.surfaceplant.piping_length.value # district heating network costs - if model.surfaceplant.enduse_option.value == PlantType.DISTRICT_HEATING: # district heat + if model.surfaceplant.plant_type.value == PlantType.DISTRICT_HEATING: # district heat if self.dhtotaldistrictnetworkcost.Provided: self.dhdistrictcost.value = self.dhtotaldistrictnetworkcost.value elif self.dhpipinglength.Provided: @@ -2136,20 +2123,18 @@ def Calculate(self, model: Model) -> None: # O&M costs # calculate first O&M costs independent of whether oamtotalfixed is provided or not # additional electricity cost for heat pump as end-use - if model.surfaceplant.enduse_option.value == PlantType.HEAT_PUMP: # heat pump: + if model.surfaceplant.plant_type.value == PlantType.HEAT_PUMP: # heat pump: self.averageannualheatpumpelectricitycost.value = np.average( model.surfaceplant.heat_pump_electricity_kwh_used.value) * model.surfaceplant.electricity_cost_to_buy.value / 1E6 # M$/year # district heating peaking fuel annual cost - if model.surfaceplant.enduse_option.value == PlantType.DISTRICT_HEATING: # district heating + if model.surfaceplant.plant_type.value == PlantType.DISTRICT_HEATING: # district heating self.annualngcost.value = model.surfaceplant.annual_ng_demand.value * self.ngprice.value / 1000 / self.peakingboilerefficiency.value # array with annual O&M cost for peaking fuel self.averageannualngcost.value = np.average(self.annualngcost.value) # calculate average annual pumping costs in case no electricity is provided - if model.surfaceplant.enduse_option.value in [EndUseOptions.HEAT, PlantType.ABSORPTION_CHILLER, - PlantType.HEAT_PUMP, PlantType.DISTRICT_HEATING]: - self.averageannualpumpingcosts.value = np.average( - model.surfaceplant.PumpingkWh.value) * model.surfaceplant.electricity_cost_to_buy.value / 1E6 # M$/year + if model.surfaceplant.plant_type.value in [PlantType.INDUSTRIAL, PlantType.ABSORPTION_CHILLER, PlantType.HEAT_PUMP, PlantType.DISTRICT_HEATING]: + self.averageannualpumpingcosts.value = np.average(model.surfaceplant.PumpingkWh.value) * model.surfaceplant.electricity_cost_to_buy.value / 1E6 # M$/year if not self.oamtotalfixed.Valid: # labor cost @@ -2193,7 +2178,7 @@ def Calculate(self, model: Model) -> None: 365. * 24. * 3600. / 1E6 * 925. / 1E6) # additional O&M cost for absorption chiller if used - if model.surfaceplant.enduse_option.value == PlantType.ABSORPTION_CHILLER: # absorption chiller: + if model.surfaceplant.plant_type.value == PlantType.ABSORPTION_CHILLER: # absorption chiller: if self.chilleropex.value == -1: self.chilleropex.value = self.chillercapex.value * 2 / 100 # assumed annual O&M for chiller is 2% of investment cost @@ -2206,7 +2191,7 @@ def Calculate(self, model: Model) -> None: self.chilleropex.value = 0 # district heating O&M cost - if model.surfaceplant.enduse_option.value == PlantType.DISTRICT_HEATING: # district heating + if model.surfaceplant.plant_type.value == PlantType.DISTRICT_HEATING: # district heating self.annualngcost.value = model.surfaceplant.annual_ng_demand.value * self.ngprice.value / 1000 # array with annual O&M cost for peaking fuel if self.dhoandmcost.Provided: diff --git a/src/geophires_x/EconomicsCCUS.py b/src/geophires_x/EconomicsCCUS.py index cec7a8f6..18574799 100644 --- a/src/geophires_x/EconomicsCCUS.py +++ b/src/geophires_x/EconomicsCCUS.py @@ -2,7 +2,6 @@ import os import math import numpy_financial as npf -from geophires_x.Model import Model from geophires_x.Economics import BuildPricingModel, Economics from geophires_x.OptionList import EndUseOptions from geophires_x.Parameter import intParameter, floatParameter, OutputParameter @@ -10,7 +9,7 @@ class EconomicsCCUS(Economics): - def __init__(self, model: Model): + def __init__(self, model): """ The __init__ function is called automatically when a class is instantiated. It initializes the attributes of an object, and sets default values for certain arguments @@ -313,7 +312,7 @@ def __init__(self, model: Model): model.logger.info("Complete " + str(__class__) + ": " + sys._getframe().f_code.co_name) - def read_parameters(self, model: Model) -> None: + def read_parameters(self, model) -> None: """ The read_parameters function reads in the parameters from a dictionary and stores them in the parameters. It also handles special cases that need to be handled after a value has been read in and checked. @@ -337,7 +336,7 @@ def read_parameters(self, model: Model) -> None: model.logger.info("complete " + str(__class__) + ": " + sys._getframe().f_code.co_name) - def Calculate(self, model: Model) -> None: + def Calculate(self, model) -> None: """ The Calculate function is where all the calculations are done. This function can be called multiple times, and will only recalculate what has changed each time it is called. diff --git a/src/geophires_x/MC_GeoPHIRES3.py b/src/geophires_x/MC_GeoPHIRES3.py index 90fed82d..947da2d3 100644 --- a/src/geophires_x/MC_GeoPHIRES3.py +++ b/src/geophires_x/MC_GeoPHIRES3.py @@ -256,6 +256,7 @@ def main(enable_geophires_logging_config=True): f.write(s) # TODO Use a scratch directory to minimize the ness: https://docs.python.org/3/library/tempfile.html#tempfile.TemporaryDirectory + # TODO Use tdqm library to show progress bar on screen: https://github.com/tqdm/tqdm # build the args list pass_list = [Inputs, Outputs, args, Outputfile, working_dir, PythonPath] # this list never changes diff --git a/src/geophires_x/Model.py b/src/geophires_x/Model.py index 9e085c84..4bf4ae30 100644 --- a/src/geophires_x/Model.py +++ b/src/geophires_x/Model.py @@ -1,23 +1,44 @@ -import sys +from pathlib import Path import logging import time import logging.config +from geophires_x.EconomicsCCUS import EconomicsCCUS +from geophires_x.EconomicsS_DAC_GT import EconomicsS_DAC_GT from geophires_x.GeoPHIRESUtils import read_input_file +from geophires_x.OutputsAddOns import OutputsAddOns +from geophires_x.OutputsCCUS import OutputsCCUS +from geophires_x.OutputsS_DAC_GT import OutputsS_DAC_GT +from geophires_x.TDPReservoir import TDPReservoir from geophires_x.WellBores import WellBores from geophires_x.SurfacePlant import SurfacePlant -from geophires_x.SurfacePlantDirectUseHeat import surface_plant_direct_use_heat -from geophires_x.SurfacePlantSubcriticalORC import surface_plant_subcritical_orc -from geophires_x.SurfacePlantSupercriticalORC import surface_plant_supercritical_orc -from geophires_x.SurfacePlantSingleFlash import surface_plant_single_flash -from geophires_x.SurfacePlantDoubleFlash import surface_plant_double_flash -from geophires_x.SurfacePlantAbsorptionChiller import surface_plant_absorption_chiller -from geophires_x.SurfacePlantDistrictHeating import surface_plant_district_heating -from geophires_x.SurfacePlantHeatPump import surface_plant_heat_pump -from geophires_x.SurfacePlantSUTRA import surface_plant_sutra +from geophires_x.SurfacePlantIndustrialHeat import SurfacePlantIndustrialHeat +from geophires_x.SurfacePlantSubcriticalORC import SurfacePlantSubcriticalOrc +from geophires_x.SurfacePlantSupercriticalORC import SurfacePlantSupercriticalOrc +from geophires_x.SurfacePlantSingleFlash import SurfacePlantSingleFlash +from geophires_x.SurfacePlantDoubleFlash import SurfacePlantDoubleFlash +from geophires_x.SurfacePlantAbsorptionChiller import SurfacePlantAbsorptionChiller +from geophires_x.SurfacePlantDistrictHeating import SurfacePlantDistrictHeating +from geophires_x.SurfacePlantHeatPump import SurfacePlantHeatPump from geophires_x.Economics import Economics from geophires_x.Outputs import Outputs from geophires_x.OptionList import EndUseOptions, PlantType +from geophires_x.CylindricalReservoir import CylindricalReservoir +from geophires_x.MPFReservoir import MPFReservoir +from geophires_x.LHSReservoir import LHSReservoir +from geophires_x.SFReservoir import SFReservoir +from geophires_x.UPPReservoir import UPPReservoir +from geophires_x.TOUGH2Reservoir import TOUGH2Reservoir +from geophires_x.SUTRAReservoir import SUTRAReservoir +from geophires_x.SUTRAWellBores import SUTRAWellBores +from geophires_x.SurfacePlantSUTRA import SurfacePlantSUTRA +from geophires_x.SUTRAEconomics import SUTRAEconomics +from geophires_x.SUTRAOutputs import SUTRAOutputs +from geophires_x.AGSWellBores import AGSWellBores +from geophires_x.SurfacePlantAGS import SurfacePlantAGS +from geophires_x.AGSEconomics import AGSEconomics +from geophires_x.AGSOutputs import AGSOutputs +from geophires_x.EconomicsAddOns import EconomicsAddOns class Model(object): @@ -35,10 +56,10 @@ def __init__(self, enable_geophires_logging_config=True): self.logger = logging.getLogger('root') if enable_geophires_logging_config: - logging.config.fileConfig('logging.conf') + logging.config.fileConfig(Path('logging.conf')) self.logger.setLevel(logging.INFO) - self.logger.info(f'Init {str(__class__)}: {sys._getframe().f_code.co_name}') + self.logger.info(f'Init {__class__}: {__name__}') # keep track of execution time self.tic = time.time() @@ -64,30 +85,22 @@ def __init__(self, enable_geophires_logging_config=True): # we need to decide which reservoir to instantiate based on the user input (InputParameters), # which we just read above for the first time # Default is Thermal drawdown percentage model (GETEM) - from .TDPReservoir import TDPReservoir as TDPReservoir self.reserv = TDPReservoir(self) if 'Reservoir Model' in self.InputParameters: if self.InputParameters['Reservoir Model'].sValue == '0': - from geophires_x.CylindricalReservoir import CylindricalReservoir as CylindricalReservoir self.reserv = CylindricalReservoir(self) # Simple Cylindrical Reservoir elif self.InputParameters['Reservoir Model'].sValue == '1': - from geophires_x.MPFReservoir import MPFReservoir as MPFReservoir self.reserv = MPFReservoir(self) # Multiple parallel fractures model (LANL) elif self.InputParameters['Reservoir Model'].sValue == '2': - from geophires_x.LHSReservoir import LHSReservoir as LHSReservoir self.reserv = LHSReservoir(self) # Multiple parallel fractures model (LANL) elif self.InputParameters['Reservoir Model'].sValue == '3': - from geophires_x.SFReservoir import SFReservoir as SFReservoir self.reserv = SFReservoir(self) # Drawdown parameter model (Tester) elif self.InputParameters['Reservoir Model'].sValue == '5': - from geophires_x.UPPReservoir import UPPReservoir as UPPReservoir self.reserv = UPPReservoir(self) # Generic user-provided temperature profile elif self.InputParameters['Reservoir Model'].sValue == '6': - from geophires_x.TOUGH2Reservoir import TOUGH2Reservoir as TOUGH2Reservoir self.reserv = TOUGH2Reservoir(self) # Tough2 is called elif self.InputParameters['Reservoir Model'].sValue == '7': - from geophires_x.SUTRAReservoir import SUTRAReservoir as SUTRAReservoir - self.reserv = SUTRAReservoir(self) # SUTRA output is read + self.reserv = SUTRAReservoir(self) # SUTRA output is created # initialize the default objects self.wellbores = WellBores(self) @@ -98,68 +111,45 @@ def __init__(self, enable_geophires_logging_config=True): if 'Reservoir Model' in self.InputParameters: if self.InputParameters['Reservoir Model'].sValue == '7': # if we use SUTRA output for simulating reservoir thermal energy storage, we use a special wellbore object that can handle SUTRA data - del self.wellbores - from geophires_x.SUTRAWellBores import SUTRAWellBores as SUTRAWellBores self.wellbores = SUTRAWellBores(self) - del self.surfaceplant - from geophires_x.SurfacePlantSUTRA import SUTRASurfacePlant as SUTRASurfacePlant - self.surfaceplant = SUTRASurfacePlant(self) - del self.economics - from geophires_x.SUTRAEconomics import SUTRAEconomics as SUTRAEconomics + self.surfaceplant = SurfacePlantSUTRA(self) self.economics = SUTRAEconomics(self) - del self.outputs - from geophires_x.SUTRAOutputs import SUTRAOutputs as SUTRAOutputs self.outputs = SUTRAOutputs(self) if 'Is AGS' in self.InputParameters: - if self.InputParameters['Is AGS'].sValue == 'True': + if self.InputParameters['Is AGS'].sValue in ['True', 'true', 'TRUE', 'T', '1']: self.logger.info("Setup the AGS elements of the Model and instantiate new attributes as needed") # If we are doing AGS, we need to replace the various objects we with versions of the objects # that have AGS functionality. # that means importing them, initializing them, then reading their parameters # use the simple cylindrical reservoir for all AGS systems. - from geophires_x.CylindricalReservoir import CylindricalReservoir as CylindricalReservoir - del self.reserv # delete the original object so we can replace it self.reserv = CylindricalReservoir(self) - del self.wellbores - from geophires_x.AGSWellBores import AGSWellBores as AGSWellBores self.wellbores = AGSWellBores(self) - del self.surfaceplant - from geophires_x.AGSSurfacePlant import AGSSurfacePlant as AGSSurfacePlant - self.surfaceplant = AGSSurfacePlant(self) - del self.economics - from geophires_x.AGSEconomics import AGSEconomics as AGSEconomics + self.surfaceplant = SurfacePlantAGS(self) self.economics = AGSEconomics(self) - from geophires_x.AGSOutputs import AGSOutputs as AGSOutputs - del self.outputs self.outputs = AGSOutputs(self) + self.wellbores.IsAGS.value = True # if we find out we have an add-ons, we need to instantiate it, then read for the parameters if 'AddOn Nickname 1' in self.InputParameters: self.logger.info("Initiate the Add-on elements") - from geophires_x.EconomicsAddOns import EconomicsAddOns # do this only is user wants add-ons self.addeconomics = EconomicsAddOns(self) - from geophires_x.OutputsAddOns import OutputsAddOns self.addoutputs = OutputsAddOns(self) # if we find out we have a ccus, we need to instantiate it, then read for the parameters if 'Ending CCUS Credit Value' in self.InputParameters: self.logger.info("Initiate the CCUS elements") - from geophires_x.EconomicsCCUS import EconomicsCCUS # do this only is user wants CCUS self.ccuseconomics = EconomicsCCUS(self) - from geophires_x.OutputsCCUS import OutputsCCUS self.ccusoutputs = OutputsCCUS(self) # if we find out we have an S-DAC-GT calculation, we need to instantiate it if 'S-DAC-GT' in self.InputParameters: if self.InputParameters['S-DAC-GT'].sValue == 'On': self.logger.info("Initiate the S-DAC-GT elements") - from geophires_x.EconomicsS_DAC_GT import EconomicsS_DAC_GT # do this only is user wants S-DAC-GT self.sdacgteconomics = EconomicsS_DAC_GT(self) - from geophires_x.OutputsS_DAC_GT import OutputsS_DAC_GT self.sdacgtoutputs = OutputsS_DAC_GT(self) - self.logger.info(f'Complete {str(__class__)}: {sys._getframe().f_code.co_name}') + self.logger.info(f'Complete {__class__}: {__name__}') def __str__(self): return "Model" @@ -169,7 +159,7 @@ def read_parameters(self) -> None: The read_parameters function reads the parameters from the input file and stores them in a dictionary. :return: None """ - self.logger.info(f'Init {str(__class__)}: {sys._getframe().f_code.co_name}') + self.logger.info(f'Init {__class__}: {__name__}') # Deal with all the parameter values that the user has provided. This is handled on a class-by-class basis. self.logger.info("Read parameters for the elements of the Model and instantiate new attributes as needed") @@ -179,6 +169,7 @@ def read_parameters(self) -> None: self.economics.read_parameters(self) self.outputs.read_parameters(self) + # having read in the parameters, we now need to set up the objects that are specific to the user's choices # if we find out we have an add-ons, read the parameters if self.economics.DoAddOnCalculations.value: self.addeconomics.read_parameters(self) @@ -192,43 +183,35 @@ def read_parameters(self) -> None: self.sdacgteconomics.read_parameters(self) self.sdacgtoutputs.read_parameters(self) - # Once we are done reading and processing parameters, we reset the objects to more specific objects based on user choices - - if self.surfaceplant.enduse_option.value not in [EndUseOptions.HEAT]: - # if we are doing power generation, we need to instantiate the surface plant object based on the user input + # Once we are done reading and processing parameters, + # we reset the objects to more specific objects based on user choices + # Handle the special case where the user defines it as AGS, but sets the temperature too high or the laterals > 1 + # in that case, we revert to the classical version of the surfaceplant + if self.wellbores.IsAGS.value and self.wellbores.Tini < 375.0 and self.wellbores.numnonverticalsections.value == 1: + self.surfaceplant = SurfacePlantAGS(self) + elif self.surfaceplant.enduse_option.value not in [EndUseOptions.HEAT]: + # if we are any doing power generation (only power, or CHP), + # we need to instantiate the surface plant object based on the user input if self.surfaceplant.plant_type.value == PlantType.SUB_CRITICAL_ORC: - self.surfaceplant = surface_plant_subcritical_orc(self) + self.surfaceplant = SurfacePlantSubcriticalOrc(self) elif self.surfaceplant.plant_type.value == PlantType.SUPER_CRITICAL_ORC: - self.surfaceplant = surface_plant_supercritical_orc(self) + self.surfaceplant = SurfacePlantSupercriticalOrc(self) elif self.surfaceplant.plant_type.value == PlantType.SINGLE_FLASH: - self.surfaceplant = surface_plant_single_flash(self) + self.surfaceplant = SurfacePlantSingleFlash(self) else: # default is double flash - self.surfaceplant = surface_plant_double_flash(self) - - # re-read the parameters for the newly instantiated surface plant - self.surfaceplant.read_parameters(self) - - # assume that if they are doing CHP of some kind, we have two surface plants we need to account for, - # and that the second surface plant is industrial heat only - if self.surfaceplant.enduse_option.value in [EndUseOptions.COGENERATION_TOPPING_EXTRA_HEAT, - EndUseOptions.COGENERATION_TOPPING_EXTRA_ELECTRICITY, - EndUseOptions.COGENERATION_BOTTOMING_EXTRA_HEAT, - EndUseOptions.COGENERATION_BOTTOMING_EXTRA_ELECTRICITY, - EndUseOptions.COGENERATION_PARALLEL_EXTRA_HEAT, - EndUseOptions.COGENERATION_PARALLEL_EXTRA_ELECTRICITY]: - self.surfaceplant2 = surface_plant_direct_use_heat(self) - self.surfaceplant2.read_parameters(self) #read the parameters for the second surface plant - else: #direct use heat only style physical plant + self.surfaceplant = SurfacePlantDoubleFlash(self) + + else: # direct use heat only style physical plant if self.surfaceplant.plant_type.value == PlantType.ABSORPTION_CHILLER: - self.surfaceplant = surface_plant_absorption_chiller(self) + self.surfaceplant = SurfacePlantAbsorptionChiller(self) elif self.surfaceplant.plant_type.value == PlantType.HEAT_PUMP: - self.surfaceplant = surface_plant_heat_pump(self) + self.surfaceplant = SurfacePlantHeatPump(self) elif self.surfaceplant.plant_type.value == PlantType.DISTRICT_HEATING: - self.surfaceplant = surface_plant_district_heating(self) + self.surfaceplant = SurfacePlantDistrictHeating(self) elif self.surfaceplant.plant_type.value == PlantType.RTES: - self.surfaceplant = surface_plant_sutra(self) + self.surfaceplant = SurfacePlantSUTRA(self) else: - self.surfaceplant = surface_plant_direct_use_heat(self) + self.surfaceplant = SurfacePlantIndustrialHeat(self) # re-read the parameters for the newly instantiated surface plant self.surfaceplant.read_parameters(self) @@ -237,7 +220,7 @@ def read_parameters(self) -> None: if self.surfaceplant.plant_type.value == PlantType.DISTRICT_HEATING: self.surfaceplant.CalculateDHDemand(self) # calculate district heating demand - self.logger.info("complete " + str(__class__) + ": " + sys._getframe().f_code.co_name) + self.logger.info("complete " + str(__class__) + ": " + __name__) def Calculate(self): """ @@ -246,7 +229,7 @@ def Calculate(self): and self.surfaceplant for later use by other functions. :return: None """ - self.logger.info(f'Init {str(__class__)}: {sys._getframe().f_code.co_name}') + self.logger.info(f'Init {__class__}: {__name__}') # calculate the results self.logger.info("Run calculations for the elements of the Model") @@ -257,15 +240,6 @@ def Calculate(self): self.wellbores.Calculate(self) # model the wellbores self.surfaceplant.Calculate(self) # model the surfaceplant - # if we are doing cogeneration, we need to calculate the values for second surface plant - if self.surfaceplant.enduse_option.value in [EndUseOptions.COGENERATION_TOPPING_EXTRA_HEAT, - EndUseOptions.COGENERATION_TOPPING_EXTRA_ELECTRICITY, - EndUseOptions.COGENERATION_BOTTOMING_EXTRA_HEAT, - EndUseOptions.COGENERATION_BOTTOMING_EXTRA_ELECTRICITY, - EndUseOptions.COGENERATION_PARALLEL_EXTRA_HEAT, - EndUseOptions.COGENERATION_PARALLEL_EXTRA_ELECTRICITY]: - self.surfaceplant2.Calculate(self) - # in case of district heating, the surface plant module may have updated the utilization factor, # and therefore we need to recalculate the modules reservoir, wellbore and surface plant. # 1 iteration should be sufficient. @@ -284,4 +258,4 @@ def Calculate(self): if self.economics.DoSDACGTCalculations.value: self.sdacgteconomics.Calculate(self) - self.logger.info(f'complete {str(__class__)}: {sys._getframe().f_code.co_name}') + self.logger.info(f'complete {__class__}: {__name__}') diff --git a/src/geophires_x/Outputs.py b/src/geophires_x/Outputs.py index 25b9ed23..fdd79643 100644 --- a/src/geophires_x/Outputs.py +++ b/src/geophires_x/Outputs.py @@ -113,7 +113,7 @@ def PrintOutputs(self, model: Model): try: outputfile = "HDR.out" if len(sys.argv) > 2: outputfile = sys.argv[2] - with open(outputfile,'w', encoding='UTF-8') as f: + with (open(outputfile,'w', encoding='UTF-8') as f): f.write(' *****************\n') f.write(' ***CASE REPORT***\n') f.write(' *****************\n') @@ -135,7 +135,7 @@ def PrintOutputs(self, model: Model): f.write(f" Average Annual Geothermal Heat Production: {sum(model.surfaceplant.dh_geothermal_heating.value * 24) / model.surfaceplant.plant_lifetime.value / 1e3:10.2f} " + model.surfaceplant.annual_heating_demand.CurrentUnits.value + NL) f.write(f" Average Annual Peaking Fuel Heat Production: {sum(model.surfaceplant.dh_natural_gas_heating.value * 24) / model.surfaceplant.plant_lifetime.value / 1e3:10.2f} " + model.surfaceplant.annual_heating_demand.CurrentUnits.value + NL) - if model.surfaceplant.enduse_option.value in [EndUseOptions.ELECTRICITY, EndUseOptions.COGENERATION_TOPPING_EXTRA_HEAT, EndUseOptions.COGENERATION_TOPPING_EXTRA_ELECTRICITY, EndUseOptions.COGENERATION_BOTTOMING_EXTRA_ELECTRICITY, EndUseOptions.COGENERATION_BOTTOMING_EXTRA_HEAT, EndUseOptions.COGENERATION_PARALLEL_EXTRA_HEAT, EndUseOptions.COGENERATION_PARALLEL_EXTRA_ELECTRICITY]: # there is an electricity componenent + if model.surfaceplant.enduse_option.value in [EndUseOptions.ELECTRICITY, EndUseOptions.COGENERATION_TOPPING_EXTRA_HEAT, EndUseOptions.COGENERATION_TOPPING_EXTRA_ELECTRICITY, EndUseOptions.COGENERATION_BOTTOMING_EXTRA_ELECTRICITY, EndUseOptions.COGENERATION_BOTTOMING_EXTRA_HEAT, EndUseOptions.COGENERATION_PARALLEL_EXTRA_HEAT, EndUseOptions.COGENERATION_PARALLEL_EXTRA_ELECTRICITY]: # there is an electricity component f.write(f" Average Net Electricity Production: {np.average(model.surfaceplant.NetElectricityProduced.value):10.2f} " + model.surfaceplant.NetElectricityProduced.CurrentUnits.value + NL) if model.surfaceplant.enduse_option.value != EndUseOptions.ELECTRICITY: # there is a direct-use component f.write(f" Average Direct-Use Heat Production: {np.average(model.surfaceplant.HeatProduced.value):10.2f} "+ model.surfaceplant.HeatProduced.CurrentUnits.value + NL) @@ -145,10 +145,11 @@ def PrintOutputs(self, model: Model): if model.surfaceplant.enduse_option.value in [EndUseOptions.ELECTRICITY, EndUseOptions.COGENERATION_TOPPING_EXTRA_HEAT, EndUseOptions.COGENERATION_BOTTOMING_EXTRA_HEAT, EndUseOptions.COGENERATION_PARALLEL_EXTRA_HEAT]: #levelized cost expressed as LCOE f.write(f" Electricity breakeven price: {model.economics.LCOE.value:10.2f} " + model.economics.LCOE.CurrentUnits.value + NL) - elif model.surfaceplant.enduse_option.value in [EndUseOptions.HEAT, EndUseOptions.COGENERATION_TOPPING_EXTRA_ELECTRICITY, EndUseOptions.COGENERATION_BOTTOMING_EXTRA_ELECTRICITY, EndUseOptions.COGENERATION_PARALLEL_EXTRA_ELECTRICITY, PlantType.HEAT_PUMP, PlantType.DISTRICT_HEATING]: #levelized cost expressed as LCOH + elif model.surfaceplant.enduse_option.value in [EndUseOptions.HEAT, EndUseOptions.COGENERATION_TOPPING_EXTRA_ELECTRICITY, EndUseOptions.COGENERATION_BOTTOMING_EXTRA_ELECTRICITY, EndUseOptions.COGENERATION_PARALLEL_EXTRA_ELECTRICITY] \ + and model.surfaceplant.plant_type.value not in [PlantType.ABSORPTION_CHILLER]: # levelized cost expressed as LCOH f.write(f" Direct-Use heat breakeven price: {model.economics.LCOH.value:10.2f} " + model.economics.LCOH.CurrentUnits.value + NL) - elif model.surfaceplant.plant_type.value == PlantType.ABSORPTION_CHILLER: + elif model.surfaceplant.enduse_option.value in [EndUseOptions.HEAT] and model.surfaceplant.plant_type.value == PlantType.ABSORPTION_CHILLER: f.write(f" Direct-Use Cooling Breakeven Price: {model.economics.LCOC.value:10.2f} " + model.economics.LCOC.CurrentUnits.value + NL) f.write(f" Number of production wells: {model.wellbores.nprod.value:10.0f}"+NL) @@ -351,13 +352,13 @@ def PrintOutputs(self, model: Model): f.write(f" Wellfield maintenance costs: {model.economics.Coamwell.value:10.2f} " + model.economics.Coamwell.CurrentUnits.value + NL) f.write(f" Power plant maintenance costs: {model.economics.Coamplant.value:10.2f} " + model.economics.Coamplant.CurrentUnits.value + NL) f.write(f" Water costs: {model.economics.Coamwater.value:10.2f} " + model.economics.Coamwater.CurrentUnits.value + NL) - if model.surfaceplant.enduse_option.value in [EndUseOptions.HEAT, PlantType.ABSORPTION_CHILLER, PlantType.HEAT_PUMP, PlantType.DISTRICT_HEATING]: + if model.surfaceplant.plant_type.value in [PlantType.INDUSTRIAL, PlantType.ABSORPTION_CHILLER, PlantType.HEAT_PUMP, PlantType.DISTRICT_HEATING]: f.write(f" Average Reservoir Pumping Cost: {model.economics.averageannualpumpingcosts.value:10.2f} " + model.economics.averageannualpumpingcosts.CurrentUnits.value + NL) - if model.surfaceplant.enduse_option.value == PlantType.ABSORPTION_CHILLER: + if model.surfaceplant.plant_type.value == PlantType.ABSORPTION_CHILLER: f.write(f" Absorption Chiller O&M Cost: {model.economics.chilleropex.value:10.2f} " + model.economics.chilleropex.CurrentUnits.value + NL) - if model.surfaceplant.enduse_option.value == PlantType.HEAT_PUMP: + if model.surfaceplant.plant_type.value == PlantType.HEAT_PUMP: f.write(f" Average Heat Pump Electricity Cost: {model.economics.averageannualheatpumpelectricitycost.value:10.2f} " + model.economics.averageannualheatpumpelectricitycost.CurrentUnits.value + NL) - if model.surfaceplant.enduse_option.value == PlantType.DISTRICT_HEATING: + if model.surfaceplant.plant_type.value == PlantType.DISTRICT_HEATING: f.write(f" Annual District Heating O&M Cost: {model.economics.dhdistrictoandmcost.value:10.2f} " + model.economics.dhdistrictoandmcost.CurrentUnits.value + NL) f.write(f" Average Annual Peaking Fuel Cost: {model.economics.averageannualngcost.value:10.2f} " + model.economics.averageannualngcost.CurrentUnits.value + NL) @@ -369,7 +370,7 @@ def PrintOutputs(self, model: Model): f.write(NL) f.write(' ***SURFACE EQUIPMENT SIMULATION RESULTS***\n') f.write(NL) - if model.surfaceplant.enduse_option.value in [EndUseOptions.ELECTRICITY, EndUseOptions.COGENERATION_TOPPING_EXTRA_HEAT, EndUseOptions.COGENERATION_TOPPING_EXTRA_ELECTRICITY, EndUseOptions.COGENERATION_BOTTOMING_EXTRA_ELECTRICITY, EndUseOptions.COGENERATION_BOTTOMING_EXTRA_HEAT, EndUseOptions.COGENERATION_PARALLEL_EXTRA_HEAT, EndUseOptions.COGENERATION_PARALLEL_EXTRA_ELECTRICITY]: #there is an electricity componenent: + if model.surfaceplant.enduse_option.value in [EndUseOptions.ELECTRICITY, EndUseOptions.COGENERATION_TOPPING_EXTRA_HEAT, EndUseOptions.COGENERATION_TOPPING_EXTRA_ELECTRICITY, EndUseOptions.COGENERATION_BOTTOMING_EXTRA_ELECTRICITY, EndUseOptions.COGENERATION_BOTTOMING_EXTRA_HEAT, EndUseOptions.COGENERATION_PARALLEL_EXTRA_HEAT, EndUseOptions.COGENERATION_PARALLEL_EXTRA_ELECTRICITY]: # there is an electricity componenent: f.write(f" Initial geofluid availability: {model.surfaceplant.Availability.value[0]:10.2f} " + model.surfaceplant.Availability.PreferredUnits.value + NL) f.write(f" Maximum Total Electricity Generation: {np.max(model.surfaceplant.ElectricityProduced.value):10.2f} " + model.surfaceplant.ElectricityProduced.PreferredUnits.value + NL) f.write(f" Average Total Electricity Generation: {np.average(model.surfaceplant.ElectricityProduced.value):10.2f} " + model.surfaceplant.ElectricityProduced.PreferredUnits.value + NL) @@ -389,16 +390,16 @@ def PrintOutputs(self, model: Model): f.write(f" Initial Net Heat Production: {model.surfaceplant.HeatProduced.value[0]:10.2f} " + model.surfaceplant.HeatProduced.PreferredUnits.value + NL) f.write(f" Average Annual Heat Production: {np.average(model.surfaceplant.HeatkWhProduced.value/1E6):10.2f} GWh" + NL) - if model.surfaceplant.enduse_option.value == PlantType.HEAT_PUMP: + if model.surfaceplant.plant_type.value == PlantType.HEAT_PUMP: f.write(f" Average Annual Heat Pump Electricity Use: {np.average(model.surfaceplant.heat_pump_electricity_kwh_used.value / 1E6):10.2f} " + "GWh/year" + NL) - if model.surfaceplant.enduse_option.value == PlantType.ABSORPTION_CHILLER: + if model.surfaceplant.plant_type.value == PlantType.ABSORPTION_CHILLER: f.write(f" Maximum Cooling Production: {np.max(model.surfaceplant.cooling_produced.value):10.2f} " + model.surfaceplant.cooling_produced.PreferredUnits.value + NL) f.write(f" Average Cooling Production: {np.average(model.surfaceplant.cooling_produced.value):10.2f} " + model.surfaceplant.cooling_produced.PreferredUnits.value + NL) f.write(f" Minimum Cooling Production: {np.min(model.surfaceplant.cooling_produced.value):10.2f} " + model.surfaceplant.cooling_produced.PreferredUnits.value + NL) f.write(f" Initial Cooling Production: {model.surfaceplant.cooling_produced.value[0]:10.2f} " + model.surfaceplant.cooling_produced.PreferredUnits.value + NL) f.write(f" Average Annual Cooling Production: {np.average(model.surfaceplant.cooling_kWh_Produced.value / 1E6):10.2f} " + "GWh/year" + NL) - if model.surfaceplant.enduse_option.value == PlantType.DISTRICT_HEATING: + if model.surfaceplant.plant_type.value == PlantType.DISTRICT_HEATING: f.write(f" Annual District Heating Demand: {model.surfaceplant.annual_heating_demand.value:10.2f} " + model.surfaceplant.annual_heating_demand.PreferredUnits.value + NL) f.write(f" Maximum Daily District Heating Demand: {np.max(model.surfaceplant.daily_heating_demand.value):10.2f} " + model.surfaceplant.daily_heating_demand.PreferredUnits.value + NL) f.write(f" Average Daily District Heating Demand: {np.average(model.surfaceplant.daily_heating_demand.value):10.2f} " + model.surfaceplant.daily_heating_demand.PreferredUnits.value + NL) @@ -428,7 +429,7 @@ def PrintOutputs(self, model: Model): model.wellbores.PumpingPower.value[i*model.economics.timestepsperyear.value], model.surfaceplant.NetElectricityProduced.value[i*model.economics.timestepsperyear.value], model.surfaceplant.FirstLawEfficiency.value[i*model.economics.timestepsperyear.value]*100)+NL) - elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT: #only direct-use + elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value not in [PlantType.HEAT_PUMP, PlantType.DISTRICT_HEATING, PlantType.ABSORPTION_CHILLER]: # only direct-use f.write(' YEAR THERMAL GEOFLUID PUMP NET\n') f.write(' DRAWDOWN TEMPERATURE POWER HEAT\n') f.write(' (deg C) (MW) (MW)\n') @@ -440,7 +441,7 @@ def PrintOutputs(self, model: Model): model.surfaceplant.HeatProduced.value[i*model.economics.timestepsperyear.value])+NL) - elif model.surfaceplant.enduse_option.value in [PlantType.HEAT_PUMP]: #heat pump + elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value in [PlantType.HEAT_PUMP]: #heat pump f.write(' YEAR THERMAL GEOFLUID PUMP NET HEAT PUMP\n') f.write(' DRAWDOWN TEMPERATURE POWER HEAT ELECTRICITY USE\n') f.write(' (deg C) (MWe) (MWt) (MWe)\n') @@ -451,7 +452,7 @@ def PrintOutputs(self, model: Model): model.wellbores.PumpingPower.value[i*model.economics.timestepsperyear.value], model.surfaceplant.HeatProduced.value[i*model.economics.timestepsperyear.value], model.surfaceplant.heat_pump_electricity_used.value[i * model.economics.timestepsperyear.value]) + NL) - elif model.surfaceplant.enduse_option.value in [PlantType.DISTRICT_HEATING]: #district heating + elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value in [PlantType.DISTRICT_HEATING]: # district heating f.write(' YEAR THERMAL GEOFLUID PUMP GEOTHERMAL\n') f.write(' DRAWDOWN TEMPERATURE POWER HEAT OUTPUT\n') f.write(' (deg C) (MWe) (MWt)\n') @@ -463,7 +464,7 @@ def PrintOutputs(self, model: Model): model.surfaceplant.HeatProduced.value[i*model.economics.timestepsperyear.value])+NL) - elif model.surfaceplant.enduse_option.value in [PlantType.ABSORPTION_CHILLER]: #absorption chiller + elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value in [PlantType.ABSORPTION_CHILLER]: #absorption chiller f.write(' YEAR THERMAL GEOFLUID PUMP NET NET\n') f.write(' DRAWDOWN TEMPERATURE POWER HEAT COOLING\n') f.write(' (deg C) (MWe) (MWt) (MWt)\n') @@ -515,7 +516,7 @@ def PrintOutputs(self, model: Model): (model.reserv.InitialReservoirHeatContent.value-model.surfaceplant.RemainingReservoirHeatContent.value[i])*100/model.reserv.InitialReservoirHeatContent.value)+NL) - elif model.surfaceplant.enduse_option.value == PlantType.ABSORPTION_CHILLER: #absorption chiller + elif model.surfaceplant.plant_type.value == PlantType.ABSORPTION_CHILLER: #absorption chiller f.write(' YEAR COOLING HEAT RESERVOIR PERCENTAGE OF\n') f.write(' PROVIDED EXTRACTED HEAT CONTENT TOTAL HEAT MINED\n') f.write(' (GWh/year) (GWh/year) (10^15 J) (%)\n') @@ -527,7 +528,7 @@ def PrintOutputs(self, model: Model): (model.reserv.InitialReservoirHeatContent.value-model.surfaceplant.RemainingReservoirHeatContent.value[i]) * 100 / model.reserv.InitialReservoirHeatContent.value)+NL) - elif model.surfaceplant.enduse_option.value == PlantType.HEAT_PUMP: #heat pump + elif model.surfaceplant.plant_type.value == PlantType.HEAT_PUMP: #heat pump f.write(' YEAR HEATING RESERVOIR HEAT HEAT PUMP RESERVOIR PERCENTAGE OF\n') f.write(' PROVIDED EXTRACTED ELECTRICITY USE HEAT CONTENT TOTAL HEAT MINED\n') f.write(' (GWh/year) (GWh/year) (GWh/year) (10^15 J) (%)\n') @@ -550,7 +551,7 @@ def PrintOutputs(self, model: Model): model.surfaceplant.RemainingReservoirHeatContent.value[i], (model.reserv.InitialReservoirHeatContent.value-model.surfaceplant.RemainingReservoirHeatContent.value[i])*100/model.reserv.InitialReservoirHeatContent.value)+NL) - elif model.surfaceplant.enduse_option.value in [PlantType.DISTRICT_HEATING]: #district-heating + elif model.surfaceplant.plant_type.value in [PlantType.DISTRICT_HEATING]: #district-heating f.write(' YEAR GEOTHERMAL PEAKING BOILER RESERVOIR HEAT RESERVOIR PERCENTAGE OF\n') f.write(' HEATING PROVIDED HEATING PROVIDED EXTRACTED HEAT CONTENT TOTAL HEAT MINED\n') f.write(' (GWh/year) (GWh/year) (GWh/year) (10^15 J) (%)\n') diff --git a/src/geophires_x/OutputsAddOns.py b/src/geophires_x/OutputsAddOns.py index 83d1b1af..8922c503 100644 --- a/src/geophires_x/OutputsAddOns.py +++ b/src/geophires_x/OutputsAddOns.py @@ -1,6 +1,5 @@ import sys from geophires_x.Outputs import Outputs -from geophires_x.Model import Model NL = "\n" @@ -9,7 +8,7 @@ class OutputsAddOns(Outputs): """ Class to handles output of the AddOns values """ - def PrintOutputs(self, model: Model): + def PrintOutputs(self, model): """ The PrintOutputs function prints the results of the AddOns to a text file and to the screen. :param model: Model: The container class of the application, giving access to everything else, including the logger diff --git a/src/geophires_x/OutputsCCUS.py b/src/geophires_x/OutputsCCUS.py index ca068040..67e421d6 100644 --- a/src/geophires_x/OutputsCCUS.py +++ b/src/geophires_x/OutputsCCUS.py @@ -1,7 +1,6 @@ import sys from geophires_x.Outputs import Outputs import numpy as np -from geophires_x.Model import Model NL = "\n" @@ -10,7 +9,7 @@ class OutputsCCUS(Outputs): """ Class to handles output of the CCUS values """ - def PrintOutputs(self, model: Model): + def PrintOutputs(self, model): """ The PrintOutputs function prints the results of the CCUS to a text file and to the screen. :param model: Model: The container class of the application, giving access to everything else, including the logger diff --git a/src/geophires_x/OutputsS_DAC_GT.py b/src/geophires_x/OutputsS_DAC_GT.py index 80692ffa..4fce8543 100644 --- a/src/geophires_x/OutputsS_DAC_GT.py +++ b/src/geophires_x/OutputsS_DAC_GT.py @@ -1,6 +1,5 @@ import sys from geophires_x.Outputs import Outputs -from geophires_x.Model import Model NL = "\n" @@ -9,7 +8,7 @@ class OutputsS_DAC_GT(Outputs): """ Class to handles output of the SDAC_GT values """ - def PrintOutputs(self, model: Model): + def PrintOutputs(self, model): """ The PrintOutputs function prints the results of the SDAC_GT to a text file and to the screen. :param model: Model: The container class of the application, giving access to everything else, including the logger diff --git a/src/geophires_x/Reservoir.py b/src/geophires_x/Reservoir.py index 391aef73..784ea575 100644 --- a/src/geophires_x/Reservoir.py +++ b/src/geophires_x/Reservoir.py @@ -810,7 +810,7 @@ def Calculate(self, model: Model) -> None: # specify time-stepping vectors self.timevector.value = np.linspace(0, model.surfaceplant.plant_lifetime.value, - model.economics.timestepsperyear.value * model.surfaceplant.plant_lifetime.value + 1) + model.economics.timestepsperyear.value * model.surfaceplant.plant_lifetime.value) self.Tresoutput.value = np.zeros(len(self.timevector.value)) if self.resoption.value != ReservoirModel.SUTRA: diff --git a/src/geophires_x/SurfacePlant.py b/src/geophires_x/SurfacePlant.py index cdea06d0..1553d817 100644 --- a/src/geophires_x/SurfacePlant.py +++ b/src/geophires_x/SurfacePlant.py @@ -31,12 +31,12 @@ def power_plant_entering_temperature(self, enduse_option: EndUseOptions, timevec """ if enduse_option in [EndUseOptions.COGENERATION_BOTTOMING_EXTRA_ELECTRICITY, EndUseOptions.COGENERATION_BOTTOMING_EXTRA_HEAT]: - TenteringPP = np.repeat(T_chp_bottom, len(timevector)) + TenteringPP = np.full(len(timevector), T_chp_bottom) else: TenteringPP = ProducedTemperature return TenteringPP - def availability_water(self, T0, T1, T2): + def availability_water(self, T0: float, T1: float, T2: float) -> float: """ Availability water: copied from GEOPHIRES v1.0 Fortran Code :param T0: T0 @@ -74,7 +74,10 @@ def reinjection_temperature(self, model: Model, ambient_temperature: float, Tent :param D22: D22 :return: injection temperature, reinjection temperature, and etau """ - Tfraction = (ambient_temperature - 5.) / 10. + if ambient_temperature < 15.: + Tfraction = (ambient_temperature - 5.) / 10. + else: + Tfraction = (ambient_temperature - 15.) / 10. etaull = C21*TenteringPP**2 + C11*TenteringPP + C01 etauul = D21*TenteringPP**2 + D11*TenteringPP + D01 etau = (1.-Tfraction)*etaull + Tfraction*etauul @@ -159,9 +162,9 @@ def annual_electricity_pumping_power(self, plant_lifetime: int, enduse_option: E # all end-use options have "heat extracted from reservoir" and pumping kWs HeatkWhExtracted = np.zeros(plant_lifetime) PumpingkWh = np.zeros(plant_lifetime) - TotalkWhProduced = np.empty(0) - NetkWhProduced = np.empty(0) - HeatkWhProduced = np.empty(0) + TotalkWhProduced = np.zeros(plant_lifetime) + NetkWhProduced = np.zeros(plant_lifetime) + HeatkWhProduced = np.zeros(plant_lifetime) for i in range(0, plant_lifetime): HeatkWhExtracted[i] = np.trapz(HeatExtracted[(0 + i * timestepsperyear):((i + 1) * timestepsperyear) + 1], @@ -391,96 +394,82 @@ def __init__(self, model: Model): # Results - used by other objects or printed in output downstream self.usebuiltinoutletplantcorrelation = self.OutputParameterDict[self.usebuiltinoutletplantcorrelation.Name] = OutputParameter( Name="usebuiltinoutletplantcorrelation", - value=False, UnitType=Units.NONE ) self.TenteringPP = self.OutputParameterDict[self.TenteringPP.Name] = OutputParameter( Name="TenteringPP", - value=[], UnitType=Units.TEMPERATURE, PreferredUnits=TemperatureUnit.CELSIUS, CurrentUnits=TemperatureUnit.CELSIUS ) self.HeatkWhExtracted = self.OutputParameterDict[self.HeatkWhExtracted.Name] = OutputParameter( Name="annual heat production", - value=[], UnitType=Units.ENERGYFREQUENCY, PreferredUnits=EnergyFrequencyUnit.GWPERYEAR, CurrentUnits=EnergyFrequencyUnit.GWPERYEAR ) self.PumpingkWh = self.OutputParameterDict[self.PumpingkWh.Name] = OutputParameter( Name="annual electricity production", - value=[], UnitType=Units.ENERGYFREQUENCY, PreferredUnits=EnergyFrequencyUnit.KWPERYEAR, CurrentUnits=EnergyFrequencyUnit.KWPERYEAR ) self.ElectricityProduced = self.OutputParameterDict[self.ElectricityProduced.Name] = OutputParameter( Name="Total Electricity Generation", - value=[0.0], UnitType=Units.POWER, PreferredUnits=PowerUnit.MW, CurrentUnits=PowerUnit.MW ) self.NetElectricityProduced = self.OutputParameterDict[self.NetElectricityProduced.Name] = OutputParameter( Name="Net Electricity Production", - value=[0.0], UnitType=Units.POWER, PreferredUnits=PowerUnit.MW, CurrentUnits=PowerUnit.MW ) self.TotalkWhProduced = self.OutputParameterDict[self.TotalkWhProduced.Name] = OutputParameter( Name="Total Electricity Generation", - value=[0.0], UnitType=Units.ENERGY, PreferredUnits=EnergyUnit.KWH, CurrentUnits=EnergyUnit.KWH ) self.NetkWhProduced = self.OutputParameterDict[self.NetkWhProduced.Name] = OutputParameter( Name="Net Electricity Generation", - value=[0.0], UnitType=Units.ENERGY, PreferredUnits=EnergyUnit.KWH, CurrentUnits=EnergyUnit.KWH ) self.FirstLawEfficiency = self.OutputParameterDict[self.FirstLawEfficiency.Name] = OutputParameter( Name="First Law Efficiency", - value=[0.0], UnitType=Units.PERCENT, PreferredUnits=PercentUnit.PERCENT, CurrentUnits=PercentUnit.PERCENT ) self.HeatExtracted = self.OutputParameterDict[self.HeatExtracted.Name] = OutputParameter( Name="Heat Extracted", - value=[0.0], UnitType=Units.POWER, PreferredUnits=PowerUnit.MW, CurrentUnits=PowerUnit.MW ) self.HeatProduced = self.OutputParameterDict[self.HeatProduced.Name] = OutputParameter( Name="Heat Produced in MW", - value=[0.0], UnitType=Units.POWER, PreferredUnits=PowerUnit.MW, CurrentUnits=PowerUnit.MW ) self.HeatkWhProduced = self.OutputParameterDict[self.HeatkWhProduced.Name] = OutputParameter( Name="Heat Produced in kWh", - value=[0.0], UnitType=Units.POWER, PreferredUnits=PowerUnit.KW, CurrentUnits=PowerUnit.KW ) self.Availability = self.OutputParameterDict[self.Availability.Name] = OutputParameter( Name="Geofluid Availability", - value=[0.0], UnitType=Units.AVAILABILITY, PreferredUnits=AvailabilityUnit.MWPERKGPERSEC, CurrentUnits=AvailabilityUnit.MWPERKGPERSEC ) self.RemainingReservoirHeatContent = self.OutputParameterDict[self.RemainingReservoirHeatContent.Name] = OutputParameter( Name="Remaining Reservoir Heat Content", - value=[0.0], UnitType=Units.POWER, PreferredUnits=PowerUnit.MW, CurrentUnits=PowerUnit.MW @@ -544,8 +533,7 @@ def read_parameters(self, model:Model) -> None: elif ParameterReadIn.sValue == str(52): ParameterToModify.value = EndUseOptions.COGENERATION_PARALLEL_EXTRA_ELECTRICITY - - if ParameterToModify.Name == "Power Plant Type": + elif ParameterToModify.Name == "Power Plant Type": if ParameterReadIn.sValue == str(1): ParameterToModify.value = PlantType.SUB_CRITICAL_ORC elif ParameterReadIn.sValue == str(2): @@ -591,7 +579,7 @@ def read_parameters(self, model:Model) -> None: if ParameterToModify.value in [PlantType.SINGLE_FLASH, PlantType.DOUBLE_FLASH]: model.wellbores.impedancemodelallowed.value = False self.setinjectionpressurefixed = True - if ParameterToModify.Name == "Plant Outlet Pressure": + elif ParameterToModify.Name == "Plant Outlet Pressure": if ParameterToModify.value < 0 or ParameterToModify.value > 10000: if self.setinjectionpressurefixed: ParameterToModify.value = 100 diff --git a/src/geophires_x/AGSSurfacePlant.py b/src/geophires_x/SurfacePlantAGS.py similarity index 86% rename from src/geophires_x/AGSSurfacePlant.py rename to src/geophires_x/SurfacePlantAGS.py index 37cd0d60..04f29940 100644 --- a/src/geophires_x/AGSSurfacePlant.py +++ b/src/geophires_x/SurfacePlantAGS.py @@ -1,17 +1,15 @@ +import numpy as np from geophires_x.WellBores import * from geophires_x.Parameter import floatParameter, OutputParameter from geophires_x.Units import * from geophires_x.OptionList import WorkingFluid, EndUseOptions from geophires_x.SurfacePlant import SurfacePlant as SurfacePlant - -# code from Koenraad -import scipy from scipy.interpolate import interpn, interp1d -class AGSSurfacePlant(SurfacePlant): +class SurfacePlantAGS(SurfacePlant): """ - AGSSurfacePlant Child class of SurfacePlant; it is the same, but has advanced AGS closed-loop functionality + SurfacePlantAGS Child class of SurfacePlant; it is the same, but has advanced AGS closed-loop functionality """ def __init__(self, model: Model): @@ -23,12 +21,11 @@ def __init__(self, model: Model): :type model: :class:`~geophires_x.Model.Model` :return: Nothing, and is used to initialize the class """ - model.logger.info("Init " + str(__class__) + ": " + sys._getframe().f_code.co_name) + model.logger.info("Init " + str(__class__) + ": " + self.__init__.__name__) # Initialize the superclass first to gain access to those variables super().__init__(model) - sclass = str(__class__).replace("", "") + self.MyClass = self.__class__.__name__ self.MyPath = os.path.abspath(__file__) self.Discount_rate = 0 self.T0 = 0 @@ -203,35 +200,30 @@ def __init__(self, model: Model): # outputs self.HeatExtracted = self.OutputParameterDict[self.HeatExtracted.Name] = OutputParameter( Name="Heat Extracted", - value=[0.0], UnitType=Units.POWER, PreferredUnits=PowerUnit.MW, CurrentUnits=PowerUnit.MW ) self.HeatProduced = self.OutputParameterDict[self.HeatProduced.Name] = OutputParameter( Name="Heat Produced in MW", - value=[0.0], UnitType=Units.POWER, PreferredUnits=PowerUnit.MW, CurrentUnits=PowerUnit.MW ) self.HeatkWhProduced = self.OutputParameterDict[self.HeatkWhProduced.Name] = OutputParameter( Name="Heat Produced", - value=[0.0], UnitType=Units.ENERGY, PreferredUnits=EnergyUnit.KWH, CurrentUnits=EnergyUnit.KWH ) self.PumpingkWh = self.OutputParameterDict[self.PumpingkWh.Name] = OutputParameter( Name="pumping power needed", - value=[], UnitType=Units.ENERGY, PreferredUnits=EnergyUnit.KWH, CurrentUnits=EnergyUnit.KWH ) self.HeatkWhExtracted = self.OutputParameterDict[self.HeatkWhExtracted.Name] = OutputParameter( Name="Heat Extracted", - value=[], UnitType=Units.ENERGY, PreferredUnits=EnergyUnit.KWH, CurrentUnits=EnergyUnit.KWH @@ -239,7 +231,6 @@ def __init__(self, model: Model): self.FirstYearElectricityProduction = self.OutputParameterDict[ self.FirstYearElectricityProduction.Name] = OutputParameter( Name="Electricity Produced in the First Year", - value=-999.0, UnitType=Units.ENERGY, PreferredUnits=EnergyUnit.KWH, CurrentUnits=EnergyUnit.KWH @@ -247,42 +238,38 @@ def __init__(self, model: Model): self.AveInstNetElectricityProduction = self.OutputParameterDict[ self.AveInstNetElectricityProduction.Name] = OutputParameter( Name="Average Net Daily Electricity Production", - value=-999.0, UnitType=Units.POWER, PreferredUnits=PowerUnit.KW, CurrentUnits=PowerUnit.KW ) self.FirstYearHeatProduction = self.OutputParameterDict[self.FirstYearHeatProduction.Name] = OutputParameter( Name="Heat Produced in the First Year", - value=-999.0, UnitType=Units.ENERGY, + UnitType=Units.ENERGY, PreferredUnits=EnergyUnit.KWH, CurrentUnits=EnergyUnit.KWH ) self.AveInstHeatProduction = self.OutputParameterDict[self.AveInstHeatProduction.Name] = OutputParameter( Name="Average Net Daily Heat Production", - value=-999.0, UnitType=Units.POWER, PreferredUnits=PowerUnit.KW, CurrentUnits=PowerUnit.KW ) self.AveProductionPressure = self.OutputParameterDict[self.AveProductionPressure.Name] = OutputParameter( Name="Average Production Pressure", - value=-999.0, UnitType=Units.PRESSURE, PreferredUnits=PressureUnit.BAR, CurrentUnits=PressureUnit.BAR ) self.AveProductionTemperature = self.OutputParameterDict[self.AveProductionTemperature.Name] = OutputParameter( Name="Average Production Temperature", - value=-999.0, UnitType=Units.TEMPERATURE, PreferredUnits=TemperatureUnit.CELSIUS, CurrentUnits=TemperatureUnit.CELSIUS ) - model.logger.info("complete " + str(__class__) + ": " + sys._getframe().f_code.co_name) + model.logger.info("complete " + str(__class__) + ": " + self.__init__.__name__) def __str__(self): - return "AGSSurfacePlant" + return "SurfacePlantAGS" def read_parameters(self, model: Model) -> None: """ @@ -293,7 +280,7 @@ def read_parameters(self, model: Model) -> None: :type model: :class:`~geophires_x.Model.Model` :return: None """ - model.logger.info("Init " + str(__class__) + ": " + sys._getframe().f_code.co_name) + model.logger.info("Init " + str(__class__) + ": " + self.read_parameters.__name__) super().read_parameters(model) # if we call super, we don't need to deal with setting the parameters here, # just deal with the special cases for the variables in this class @@ -310,9 +297,9 @@ def read_parameters(self, model: Model) -> None: # handle special cases if ParameterToModify.Name == "End-Use Option": - if ParameterReadIn.sValue == str(1): + if ParameterReadIn.sValue == '1': ParameterToModify.value = EndUseOptions.ELECTRICITY - elif ParameterReadIn.sValue == str(2): + elif ParameterReadIn.sValue == '2': ParameterToModify.value = EndUseOptions.HEAT else: model.logger.info("No parameters read because no content provided") @@ -325,11 +312,12 @@ def read_parameters(self, model: Model) -> None: self.Discount_rate = model.economics.discountrate.value # same units are GEOPHIRES # initialize some arrays - self.HeatkWhProduced.value = [0.0] * model.surfaceplant.plant_lifetime.value # initialize the array - self.HeatkWhExtracted.value = [0.0] * model.surfaceplant.plant_lifetime.value # initialize the array - self.PumpingkWh.value = [0.0] * model.surfaceplant.plant_lifetime.value # initialize the array - model.logger.info("complete " + str(__class__) + ": " + sys._getframe().f_code.co_name) + self.HeatkWhProduced.value = np.zeros(model.surfaceplant.plant_lifetime.value) # initialize the array + self.HeatkWhExtracted.value = np.zeros(model.surfaceplant.plant_lifetime.value) # initialize the array + self.PumpingkWh.value = np.zeros(model.surfaceplant.plant_lifetime.value) # initialize the array + + model.logger.info("complete " + str(__class__) + ": " + self.read_parameters.__name__) def verify(self, model: Model) -> int: """ @@ -722,74 +710,71 @@ def Calculate(self, model: Model) -> None: :return: None """ model.logger.info("Init " + str(__class__) + ": " + sys._getframe().f_code.co_name) - if (model.wellbores.Tini > 375.0) or (model.wellbores.numnonverticalsections.value > 1): - # must be a multilateral setup or too hot for CLGS, so must try to use the parent code. - super().Calculate(model) # run the parent calculation + + err = self.verify(model) + if err > 0: + model.logger.fatal("Error: GEOPHIRES failed to Failed to validate CLGS input value. Exiting....") + print("Error: GEOPHIRES failed to Failed to validate CLGS input value. Exiting....") + sys.exit() + self.initialize(model) + + self.Linear_production_temperature = model.wellbores.InterpolatedTemperatureArray + self.Linear_production_pressure = model.wellbores.InterpolatedPressureArray + self.AveProductionTemperature.value = np.average(self.Linear_production_temperature) + self.AveProductionPressure.value = np.average(self.Linear_production_pressure) / 1e5 # [bar] + if min(self.Linear_production_temperature) > model.wellbores.Tinj.value: + self.calculateheatproduction(model) + if self.End_use == EndUseOptions.ELECTRICITY: + self.calculateelectricityproduction(model) else: - err = self.verify(model) - if err > 0: - model.logger.fatal("Error: GEOPHIRES failed to Failed to validate CLGS input value. Exiting....") - print("Error: GEOPHIRES failed to Failed to validate CLGS input value. Exiting....") - sys.exit() - self.initialize(model) - - self.Linear_production_temperature = model.wellbores.InterpolatedTemperatureArray - self.Linear_production_pressure = model.wellbores.InterpolatedPressureArray - self.AveProductionTemperature.value = np.average(self.Linear_production_temperature) - self.AveProductionPressure.value = np.average(self.Linear_production_pressure) / 1e5 # [bar] - if min(self.Linear_production_temperature) > model.wellbores.Tinj.value: - self.calculateheatproduction(model) - if self.End_use == EndUseOptions.ELECTRICITY: - self.calculateelectricityproduction(model) - else: - # Production temperature went below injection temperature - self.error_codes = np.append(self.error_codes, 1000) - - # Now transfer the results to the GEOPHIRES-X arrays: Deep Copy the Arrays - model.wellbores.ProducedTemperature.value = self.Linear_production_temperature.copy() - self.TenteringPP.value = model.wellbores.ProducedTemperature.value - model.wellbores.PumpingPower.value = self.Annual_pumping_power.copy() - self.HeatExtracted.value = self.Instantaneous_heat_production.copy() - # convert to MW because that is what GEOPHIRES expects - self.HeatExtracted.value = self.HeatExtracted.value / 1000.0 - # useful direct-use heat provided to application [MWth] - self.HeatProduced.value = self.HeatExtracted.value * self.enduseefficiencyfactor.value + # Production temperature went below injection temperature + self.error_codes = np.append(self.error_codes, 1000) + + # Now transfer the results to the GEOPHIRES-X arrays: Deep Copy the Arrays + model.wellbores.ProducedTemperature.value = self.Linear_production_temperature.copy() + self.TenteringPP.value = model.wellbores.ProducedTemperature.value + model.wellbores.PumpingPower.value = self.Annual_pumping_power.copy() + self.HeatExtracted.value = self.Instantaneous_heat_production.copy() + # convert to MW because that is what GEOPHIRES expects + self.HeatExtracted.value = self.HeatExtracted.value / 1000.0 + # useful direct-use heat provided to application [MWth] + self.HeatProduced.value = self.HeatExtracted.value * self.enduseefficiencyfactor.value + for i in range(0, self.plant_lifetime.value): + self.HeatkWhExtracted.value[i] = np.trapz(self.HeatExtracted.value[ + (i * model.economics.timestepsperyear.value):(( + i + 1) * model.economics.timestepsperyear.value) + 1], + dx=1. / model.economics.timestepsperyear.value * 365. * 24.) * 1000. * self.utilization_factor.value + self.PumpingkWh.value[i] = np.trapz(model.wellbores.PumpingPower.value[ + (i * model.economics.timestepsperyear.value):(( + i + 1) * model.economics.timestepsperyear.value) + 1], + dx=1. / model.economics.timestepsperyear.value * 365. * 24.) * 1000. * self.utilization_factor.value + + self.RemainingReservoirHeatContent.value = model.reserv.InitialReservoirHeatContent.value - np.cumsum( + self.HeatkWhExtracted.value) * 3600 * 1E3 / 1E15 + + if self.End_use != EndUseOptions.ELECTRICITY: + self.HeatkWhProduced.value = np.zeros(self.plant_lifetime.value) for i in range(0, self.plant_lifetime.value): - self.HeatkWhExtracted.value[i] = np.trapz(self.HeatExtracted.value[ - (i * model.economics.timestepsperyear.value):(( - i + 1) * model.economics.timestepsperyear.value) + 1], - dx=1. / model.economics.timestepsperyear.value * 365. * 24.) * 1000. * self.utilization_factor.value - self.PumpingkWh.value[i] = np.trapz(model.wellbores.PumpingPower.value[ - (i * model.economics.timestepsperyear.value):(( - i + 1) * model.economics.timestepsperyear.value) + 1], - dx=1. / model.economics.timestepsperyear.value * 365. * 24.) * 1000. * self.utilization_factor.value - - self.RemainingReservoirHeatContent.value = model.reserv.InitialReservoirHeatContent.value - np.cumsum( - self.HeatkWhExtracted.value) * 3600 * 1E3 / 1E15 - - if self.End_use != EndUseOptions.ELECTRICITY: - self.HeatkWhProduced.value = np.zeros(self.plant_lifetime.value) - for i in range(0, self.plant_lifetime.value): - self.HeatkWhProduced.value[i] = np.trapz(self.HeatProduced.value[ - (0 + i * model.economics.timestepsperyear.value):(( - i + 1) * model.economics.timestepsperyear.value) + 1], - dx=1. / model.economics.timestepsperyear.value * 365. * 24.) * 1000. * self.utilization_factor.value - else: - # copy some arrays so we have a GEOPHIRES equivalent - self.TotalkWhProduced.value = self.Annual_electricity_production.copy() - self.ElectricityProduced.value = self.Annual_electricity_production.copy() / 8760.0 / 1000.0 - f = interp1d(np.arange(0, len(self.ElectricityProduced.value)), self.ElectricityProduced.value, - fill_value="extrapolate") - self.ElectricityProduced.value = f(np.arange(0, 40, 1.0)) - self.NetElectricityProduced.value = self.Inst_Net_Electricity_production.copy() - # covert to MW, which is what GEOPHIRES expects - self.NetElectricityProduced.value = self.NetElectricityProduced.value / 1000.0 - f = interp1d(np.arange(0, len(self.NetElectricityProduced.value)), self.NetElectricityProduced.value, - fill_value="extrapolate") - self.NetElectricityProduced.value = f(np.arange(0, 40, 1.0)) - self.NetkWhProduced.value = (self.NetElectricityProduced.value * 1000.0) * 8760.0 - - self.FirstLawEfficiency.value = (self.NetElectricityProduced.value * 1000.0) / self.AveInstHeatProduction.value + self.HeatkWhProduced.value[i] = np.trapz(self.HeatProduced.value[ + (0 + i * model.economics.timestepsperyear.value):(( + i + 1) * model.economics.timestepsperyear.value) + 1], + dx=1. / model.economics.timestepsperyear.value * 365. * 24.) * 1000. * self.utilization_factor.value + else: + # copy some arrays so we have a GEOPHIRES equivalent + self.TotalkWhProduced.value = self.Annual_electricity_production.copy() + self.ElectricityProduced.value = self.Annual_electricity_production.copy() / 8760.0 / 1000.0 + f = interp1d(np.arange(0, len(self.ElectricityProduced.value)), self.ElectricityProduced.value, + fill_value="extrapolate") + self.ElectricityProduced.value = f(np.arange(0, 40, 1.0)) + self.NetElectricityProduced.value = self.Inst_Net_Electricity_production.copy() + # covert to MW, which is what GEOPHIRES expects + self.NetElectricityProduced.value = self.NetElectricityProduced.value / 1000.0 + f = interp1d(np.arange(0, len(self.NetElectricityProduced.value)), self.NetElectricityProduced.value, + fill_value="extrapolate") + self.NetElectricityProduced.value = f(np.arange(0, 40, 1.0)) + self.NetkWhProduced.value = (self.NetElectricityProduced.value * 1000.0) * 8760.0 + + self.FirstLawEfficiency.value = (self.NetElectricityProduced.value * 1000.0) / self.AveInstHeatProduction.value # handle errors if len(self.error_codes) > 0: @@ -800,6 +785,3 @@ def Calculate(self, model: Model) -> None: raise RuntimeError(base_msg) model.logger.info(f"complete {str(__class__)}: {sys._getframe().f_code.co_name}") - - def __str__(self): - return "AGSSurfacePlant" diff --git a/src/geophires_x/SurfacePlantAbsorptionChiller.py b/src/geophires_x/SurfacePlantAbsorptionChiller.py index 7ac9aaf6..a382dc99 100644 --- a/src/geophires_x/SurfacePlantAbsorptionChiller.py +++ b/src/geophires_x/SurfacePlantAbsorptionChiller.py @@ -5,7 +5,7 @@ import geophires_x.Model as Model -class surface_plant_absorption_chiller(SurfacePlant): +class SurfacePlantAbsorptionChiller(SurfacePlant): def __init__(self, model: Model): """ The __init__ function is called automatically when a class is instantiated. @@ -51,14 +51,12 @@ def __init__(self, model: Model): # Output Parameters self.cooling_produced = self.OutputParameterDict[self.cooling_produced.Name] = OutputParameter( Name="Cooling Produced", - value=[0.0], UnitType=Units.POWER, PreferredUnits=PowerUnit.MW, CurrentUnits=PowerUnit.MW ) self.cooling_kWh_Produced = self.OutputParameterDict[self.cooling_kWh_Produced.Name] = OutputParameter( Name="Annual Cooling Produced", - value=[0.0], UnitType=Units.ENERGYFREQUENCY, PreferredUnits=EnergyFrequencyUnit.KWhPERYEAR, CurrentUnits=EnergyFrequencyUnit.KWhPERYEAR @@ -67,7 +65,7 @@ def __init__(self, model: Model): model.logger.info(f"Complete {self.__class__.__name__}: {__name__}") def __str__(self): - return "surface_plant_absorption_chiller" + return "SurfacePlantAbsorptionChiller" def read_parameters(self, model: Model) -> None: """ diff --git a/src/geophires_x/SurfacePlantDistrictHeating.py b/src/geophires_x/SurfacePlantDistrictHeating.py index ed358370..43d37719 100644 --- a/src/geophires_x/SurfacePlantDistrictHeating.py +++ b/src/geophires_x/SurfacePlantDistrictHeating.py @@ -8,7 +8,7 @@ import geophires_x.Model as Model -class surface_plant_district_heating(SurfacePlant): +class SurfacePlantDistrictHeating(SurfacePlant): def __init__(self, model: Model): """ The __init__ function is called automatically when a class is instantiated. @@ -118,33 +118,28 @@ def __init__(self, model: Model): # Results - used by other objects or printed in output downstream self.hourly_heating_demand = self.OutputParameterDict[self.hourly_heating_demand.Name] = OutputParameter( Name="Hourly Heating Demand", - value=[0.0], UnitType=Units.ENERGYFREQUENCY, PreferredUnits=EnergyFrequencyUnit.MWhPERHOUR, CurrentUnits=EnergyFrequencyUnit.MWhPERHOUR ) self.daily_heating_demand = self.OutputParameterDict[self.daily_heating_demand.Name] = OutputParameter( Name="Daily Heating Demand", - value=[0.0], UnitType=Units.ENERGYFREQUENCY, PreferredUnits=EnergyFrequencyUnit.MWhPERDAY, CurrentUnits=EnergyFrequencyUnit.MWhPERDAY ) self.annual_heating_demand = self.OutputParameterDict[self.annual_heating_demand.Name] = OutputParameter( Name="Annual Heating Demand", - value=[0.0], UnitType=Units.ENERGYFREQUENCY, PreferredUnits=EnergyFrequencyUnit.GWhPERYEAR, CurrentUnits=EnergyFrequencyUnit.GWhPERYEAR ) self.util_factor_array = self.OutputParameterDict[self.util_factor_array.Name] = OutputParameter( Name="Utilisation Factor Array", - value=[0.0], UnitType=Units.NONE ) self.annual_ng_demand = self.OutputParameterDict[self.annual_ng_demand.Name] = OutputParameter( Name="Annual Peaking Boiler Natural Gas Demand", - value=[0.0], UnitType=Units.ENERGYFREQUENCY, PreferredUnits=EnergyFrequencyUnit.MWhPERYEAR, CurrentUnits=EnergyFrequencyUnit.MWhPERYEAR @@ -152,21 +147,18 @@ def __init__(self, model: Model): self.max_peaking_boiler_demand = self.OutputParameterDict[ self.max_peaking_boiler_demand.Name] = OutputParameter( Name="Maximum Peaking Boiler Natural Gas Demand", - value=[0.0], UnitType=Units.POWER, PreferredUnits=PowerUnit.MW, CurrentUnits=PowerUnit.MW ) self.dh_geothermal_heating = self.OutputParameterDict[self.dh_geothermal_heating.Name] = OutputParameter( Name="Instantaneous Geothermal Heating Over Lifetime", - value=[0.0], UnitType=Units.POWER, PreferredUnits=PowerUnit.MW, CurrentUnits=PowerUnit.MW ) self.dh_natural_gas_heating = self.OutputParameterDict[self.dh_natural_gas_heating.Name] = OutputParameter( Name="Instantaneous Natural Gas Heating Over Lifetime", - value=[0.0], UnitType=Units.POWER, PreferredUnits=PowerUnit.MW, CurrentUnits=PowerUnit.MW @@ -416,7 +408,11 @@ def calc_util_factor(self, heat_produced, time_steps_per_year): # compare thermal demand with supply current_index = i * 365 + j current_time = i + j / 365 - current_heat_output = np.interp(current_time, np.arange(0, self.plant_lifetime.value + 0.01, 1 / time_steps_per_year), heat_produced) + xp = np.arange(0, self.plant_lifetime.value + 0.01, 1 / time_steps_per_year) + fp = heat_produced + xp = xp[:len(fp)] + current_heat_output = np.interp(current_time, xp, fp) +# current_heat_output = np.interp(current_time, np.arange(0, self.plant_lifetime.value + 0.01, 1 / time_steps_per_year), heat_produced) current_heat_output_stored[current_index] = current_heat_output if self.daily_heating_demand.value[j] / 24 > current_heat_output: actual_geothermal_used[current_index] = current_heat_output diff --git a/src/geophires_x/SurfacePlantDoubleFlash.py b/src/geophires_x/SurfacePlantDoubleFlash.py index fdd823fc..67987488 100644 --- a/src/geophires_x/SurfacePlantDoubleFlash.py +++ b/src/geophires_x/SurfacePlantDoubleFlash.py @@ -5,7 +5,7 @@ import geophires_x.Model as Model -class surface_plant_double_flash(SurfacePlant): +class SurfacePlantDoubleFlash(SurfacePlant): def __init__(self, model: Model): """ The __init__ function is called automatically when a class is instantiated. diff --git a/src/geophires_x/SurfacePlantHeatPump.py b/src/geophires_x/SurfacePlantHeatPump.py index 216968fd..09316b65 100644 --- a/src/geophires_x/SurfacePlantHeatPump.py +++ b/src/geophires_x/SurfacePlantHeatPump.py @@ -7,7 +7,7 @@ import geophires_x.Model as Model -class surface_plant_heat_pump(SurfacePlant): +class SurfacePlantHeatPump(SurfacePlant): def __init__(self, model: Model): """ The __init__ function is called automatically when a class is instantiated. @@ -54,14 +54,12 @@ def __init__(self, model: Model): # Results - used by other objects or printed in output downstream self.heat_pump_electricity_used = self.OutputParameterDict[self.heat_pump_electricity_used.Name] = OutputParameter( Name="Heat Pump Electricity Consumed", - value=[0.0], UnitType=Units.POWER, PreferredUnits=PowerUnit.MW, CurrentUnits=PowerUnit.MW ) self.heat_pump_electricity_kwh_used = self.OutputParameterDict[self.heat_pump_electricity_kwh_used.Name] = OutputParameter( Name = "Annual Heat Pump Electricity Consumption", - value=[0.0], UnitType=Units.ENERGYFREQUENCY, PreferredUnits=EnergyFrequencyUnit.KWhPERYEAR, CurrentUnits=EnergyFrequencyUnit.KWhPERYEAR @@ -70,7 +68,7 @@ def __init__(self, model: Model): model.logger.info("Complete " + str(__class__) + ": " + inspect.currentframe().f_code.co_name) def __str__(self): - return "surface_plant_heat_pump" + return "SurfacePlantHeatPump" def read_parameters(self, model:Model) -> None: """ diff --git a/src/geophires_x/SurfacePlantDirectUseHeat.py b/src/geophires_x/SurfacePlantIndustrialHeat.py similarity index 98% rename from src/geophires_x/SurfacePlantDirectUseHeat.py rename to src/geophires_x/SurfacePlantIndustrialHeat.py index 91fd629a..5059f26c 100644 --- a/src/geophires_x/SurfacePlantDirectUseHeat.py +++ b/src/geophires_x/SurfacePlantIndustrialHeat.py @@ -4,7 +4,7 @@ import geophires_x.Model as Model -class surface_plant_direct_use_heat(SurfacePlant): +class SurfacePlantIndustrialHeat(SurfacePlant): def __init__(self, model: Model): """ The __init__ function is called automatically when a class is instantiated. @@ -29,7 +29,7 @@ def __init__(self, model: Model): model.logger.info("Complete " + self.__class__.__name__ + ": " + __name__) def __str__(self): - return "surface_plant_direct_use_heat" + return "SurfacePlantIndustrialHeat" def read_parameters(self, model: Model) -> None: """ diff --git a/src/geophires_x/SurfacePlantSUTRA.py b/src/geophires_x/SurfacePlantSUTRA.py index 4db1a400..54980e37 100644 --- a/src/geophires_x/SurfacePlantSUTRA.py +++ b/src/geophires_x/SurfacePlantSUTRA.py @@ -6,7 +6,7 @@ import geophires_x.Model as Model -class surface_plant_sutra(SurfacePlant): +class SurfacePlantSUTRA(SurfacePlant): def __init__(self, model: Model): """ The __init__ function is called automatically when a class is instantiated. @@ -40,7 +40,6 @@ def __init__(self, model: Model): # Results - used by other objects or printed in output downstream self.SUTRATimeStep = self.OutputParameterDict[self.SUTRATimeStep.Name] = OutputParameter( Name="Time Step used in SUTRA", - value=[0.0], UnitType=Units.TIME, PreferredUnits=TimeUnit.HOUR, CurrentUnits=TimeUnit.HOUR @@ -48,14 +47,12 @@ def __init__(self, model: Model): self.HeatInjected = self.OutputParameterDict[self.HeatInjected.Name] = OutputParameter( Name="Heat Injected", - value=[0.0], UnitType=Units.POWER, PreferredUnits=PowerUnit.MW, CurrentUnits=PowerUnit.MW ) self.HeatProduced = self.OutputParameterDict[self.HeatProduced.Name] = OutputParameter( Name="Heat Produced", - value=[0.0], UnitType=Units.POWER, PreferredUnits=PowerUnit.MW, CurrentUnits=PowerUnit.MW @@ -63,7 +60,6 @@ def __init__(self, model: Model): self.AuxiliaryHeatProduced = self.OutputParameterDict[self.AuxiliaryHeatProduced.Name] = OutputParameter( Name="Auxiliary Heat Produced", - value=[0.0], UnitType=Units.POWER, PreferredUnits=PowerUnit.MW, CurrentUnits=PowerUnit.MW @@ -71,7 +67,6 @@ def __init__(self, model: Model): self.TotalHeatProduced = self.OutputParameterDict[self.TotalHeatProduced.Name] = OutputParameter( Name="Total Heat Produced", - value=[0.0], UnitType=Units.POWER, PreferredUnits=PowerUnit.MW, CurrentUnits=PowerUnit.MW @@ -79,7 +74,6 @@ def __init__(self, model: Model): self.AnnualHeatInjected = self.OutputParameterDict[self.AnnualHeatInjected.Name] = OutputParameter( Name="Annual Heat Injected", - value=[0.0], UnitType=Units.ENERGYFREQUENCY, PreferredUnits=EnergyFrequencyUnit.GWhPERYEAR, CurrentUnits=EnergyFrequencyUnit.GWhPERYEAR @@ -87,7 +81,6 @@ def __init__(self, model: Model): self.AnnualHeatProduced = self.OutputParameterDict[self.AnnualHeatProduced.Name] = OutputParameter( Name="Annual Heat Produced", - value=[0.0], UnitType=Units.ENERGYFREQUENCY, PreferredUnits=EnergyFrequencyUnit.GWhPERYEAR, CurrentUnits=EnergyFrequencyUnit.GWhPERYEAR @@ -95,7 +88,6 @@ def __init__(self, model: Model): self.AnnualAuxiliaryHeatProduced = self.OutputParameterDict[self.AnnualAuxiliaryHeatProduced.Name] = OutputParameter( Name="Annual Auxiliary Heat Produced", - value=[0.0], UnitType=Units.ENERGYFREQUENCY, PreferredUnits=EnergyFrequencyUnit.GWhPERYEAR, CurrentUnits=EnergyFrequencyUnit.GWhPERYEAR @@ -103,7 +95,6 @@ def __init__(self, model: Model): self.AnnualTotalHeatProduced = self.OutputParameterDict[self.AnnualTotalHeatProduced.Name] = OutputParameter( Name="Annual Total Heat Produced", - value=[0.0], UnitType=Units.ENERGYFREQUENCY, PreferredUnits=EnergyFrequencyUnit.GWhPERYEAR, CurrentUnits=EnergyFrequencyUnit.GWhPERYEAR @@ -111,7 +102,6 @@ def __init__(self, model: Model): self.PumpingkWh = self.OutputParameterDict[self.PumpingkWh.Name] = OutputParameter( Name="Annual Pumping Electricity Required", - value=[], UnitType=Units.ENERGYFREQUENCY, PreferredUnits=EnergyFrequencyUnit.KWhPERYEAR, CurrentUnits=EnergyFrequencyUnit.KWhPERYEAR @@ -119,7 +109,6 @@ def __init__(self, model: Model): self.maxpeakingboilerdemand = self.OutputParameterDict[self.maxpeakingboilerdemand.Name] = OutputParameter( Name = "Maximum Peaking Boiler Natural Gas Demand", - value=[0.0], UnitType = Units.POWER, PreferredUnits = PowerUnit.MW, CurrentUnits = PowerUnit.MW @@ -128,14 +117,12 @@ def __init__(self, model: Model): #heat pump (potentially used in the future) self.HeatPumpElectricityUsed = self.OutputParameterDict[self.HeatPumpElectricityUsed.Name] = OutputParameter( Name = "Heat Pump Electricity Consumed", - value=[0.0], UnitType = Units.POWER, PreferredUnits = PowerUnit.MW, CurrentUnits = PowerUnit.MW ) self.HeatPumpElectricitykWhUsed = self.OutputParameterDict[self.HeatPumpElectricitykWhUsed.Name] = OutputParameter( Name = "Annual Heat Pump Electricity Consumption", - value=[0.0], UnitType = Units.ENERGYFREQUENCY, PreferredUnits = EnergyFrequencyUnit.KWhPERYEAR, CurrentUnits = EnergyFrequencyUnit.KWhPERYEAR diff --git a/src/geophires_x/SurfacePlantSingleFlash.py b/src/geophires_x/SurfacePlantSingleFlash.py index d4c0891d..bd845ab7 100644 --- a/src/geophires_x/SurfacePlantSingleFlash.py +++ b/src/geophires_x/SurfacePlantSingleFlash.py @@ -5,7 +5,7 @@ from geophires_x.SurfacePlant import SurfacePlant import geophires_x.Model as Model -class surface_plant_single_flash(SurfacePlant): +class SurfacePlantSingleFlash(SurfacePlant): def __init__(self, model: Model): """ The __init__ function is called automatically when a class is instantiated. diff --git a/src/geophires_x/SurfacePlantSubcriticalORC.py b/src/geophires_x/SurfacePlantSubcriticalORC.py index 24f10853..3ce80f50 100644 --- a/src/geophires_x/SurfacePlantSubcriticalORC.py +++ b/src/geophires_x/SurfacePlantSubcriticalORC.py @@ -1,11 +1,9 @@ from pathlib import Path -import numpy as np -from geophires_x.OptionList import EndUseOptions from geophires_x.SurfacePlant import SurfacePlant import geophires_x.Model as Model -class surface_plant_subcritical_orc(SurfacePlant): +class SurfacePlantSubcriticalOrc(SurfacePlant): def __init__(self, model: Model): """ The __init__ function is called automatically when a class is instantiated. diff --git a/src/geophires_x/SurfacePlantSupercriticalORC.py b/src/geophires_x/SurfacePlantSupercriticalORC.py index d8b9e736..8a115521 100644 --- a/src/geophires_x/SurfacePlantSupercriticalORC.py +++ b/src/geophires_x/SurfacePlantSupercriticalORC.py @@ -2,7 +2,7 @@ import geophires_x.Model as Model -class surface_plant_supercritical_orc(SurfacePlant): +class SurfacePlantSupercriticalOrc(SurfacePlant): def __init__(self, model: Model): """ The __init__ function is called automatically when a class is instantiated. diff --git a/src/geophires_x/WellBores.py b/src/geophires_x/WellBores.py index 1c8f63a2..1c78601f 100644 --- a/src/geophires_x/WellBores.py +++ b/src/geophires_x/WellBores.py @@ -508,7 +508,7 @@ def __init__(self, model: Model): :type model: :class:`~geophires_x.Model.Model` :return: Nothing, and is used to initialize the class """ - model.logger.info("Init " + str(__class__) + ": " + sys._getframe().f_code.co_name) + model.logger.info(f"Init {self.__class__.__name__}: {__name__}") self.rhowaterprod = self.rhowaterinj = 0.0 # Set up all the Parameters that will be predefined by this class using the different types of parameter classes. @@ -742,9 +742,9 @@ def __init__(self, model: Model): self.usebuiltinhydrostaticpressurecorrelation = True self.usebuiltinppwellheadcorrelation = True self.Pminimum = 0.0 - sclass = str(__class__).replace("", "") - self.MyPath = os.path.abspath(__file__) + sclass = self.__class__.__name__ + self.MyClass = sclass + self.MyPath = __file__ # Results - used by other objects or printed in output downstream self.Phydrostaticcalc = self.OutputParameterDict[self.Phydrostaticcalc.Name] = floatParameter( @@ -756,132 +756,114 @@ def __init__(self, model: Model): ) self.redrill = self.OutputParameterDict[self.redrill.Name] = OutputParameter( Name="redrill", - value=0, UnitType=Units.NONE ) self.PumpingPowerProd = self.OutputParameterDict[self.PumpingPowerProd.Name] = OutputParameter( Name="PumpingPowerProd", - value=[0.0], UnitType=Units.POWER, PreferredUnits=PowerUnit.MW, CurrentUnits=PowerUnit.MW ) self.PumpingPowerInj = self.OutputParameterDict[self.PumpingPowerInj.Name] = OutputParameter( Name="PumpingPowerInj", - value=[0.0], UnitType=Units.POWER, PreferredUnits=PowerUnit.MW, CurrentUnits=PowerUnit.MW ) self.pumpdepth = self.OutputParameterDict[self.pumpdepth.Name] = OutputParameter( Name="pumpdepth", - value=[0.0], UnitType=Units.LENGTH, PreferredUnits=LengthUnit.METERS, CurrentUnits=LengthUnit.METERS ) self.impedancemodelallowed = self.OutputParameterDict[self.impedancemodelallowed.Name] = OutputParameter( Name="impedancemodelallowed", - value=True, UnitType=Units.NONE ) self.productionwellpumping = self.OutputParameterDict[self.productionwellpumping.Name] = OutputParameter( Name="productionwellpumping", - value=True, UnitType=Units.NONE ) self.impedancemodelused = self.OutputParameterDict[self.impedancemodelused.Name] = OutputParameter( Name="impedancemodelused", - value=False, UnitType=Units.NONE ) self.ProdTempDrop = self.OutputParameterDict[self.ProdTempDrop.Name] = OutputParameter( Name="Production Well Temperature Drop", - value=[0.0], UnitType=Units.TEMPERATURE, PreferredUnits=TemperatureUnit.CELSIUS, CurrentUnits=TemperatureUnit.CELSIUS ) self.DPOverall = self.OutputParameterDict[self.DPOverall.Name] = OutputParameter( Name="Total Pressure Drop", - value=[0.0], UnitType=Units.PRESSURE, PreferredUnits=PressureUnit.KPASCAL, CurrentUnits=PressureUnit.KPASCAL ) self.DPInjWell = self.OutputParameterDict[self.DPInjWell.Name] = OutputParameter( Name="Injection Well Pressure Drop", - value=[0.0], UnitType=Units.PRESSURE, PreferredUnits=PressureUnit.KPASCAL, CurrentUnits=PressureUnit.KPASCAL ) self.DPReserv = self.OutputParameterDict[self.DPReserv.Name] = OutputParameter( Name="Reservoir Pressure Drop", - value=[0.0], UnitType=Units.PRESSURE, PreferredUnits=PressureUnit.KPASCAL, CurrentUnits=PressureUnit.KPASCAL ) self.DPProdWell = self.OutputParameterDict[self.DPProdWell.Name] = OutputParameter( Name="Production Well Pump Pressure Drop", - value=[0.0], UnitType=Units.PRESSURE, PreferredUnits=PressureUnit.KPASCAL, CurrentUnits=PressureUnit.KPASCAL ) self.DPBouyancy = self.OutputParameterDict[self.DPBouyancy.Name] = OutputParameter( Name="Bouyancy Pressure Drop", - value=[0.0], UnitType=Units.PRESSURE, PreferredUnits=PressureUnit.KPASCAL, CurrentUnits=PressureUnit.KPASCAL ) self.ProducedTemperature = self.OutputParameterDict[self.ProducedTemperature.Name] = OutputParameter( Name="Produced Temperature", - value=[0.0], UnitType=Units.TEMPERATURE, PreferredUnits=TemperatureUnit.CELSIUS, CurrentUnits=TemperatureUnit.CELSIUS ) self.PumpingPower = self.OutputParameterDict[self.PumpingPower.Name] = OutputParameter( Name="Pumping Power", - value=[0.0], UnitType=Units.POWER, PreferredUnits=PowerUnit.MW, CurrentUnits=PowerUnit.MW ) self.Pprodwellhead = self.OutputParameterDict[self.Pprodwellhead.Name] = OutputParameter( Name="Production wellhead pressure", - value=-999.0, UnitType=Units.PRESSURE, PreferredUnits=PressureUnit.KPASCAL, CurrentUnits=PressureUnit.KPASCAL ) - model.logger.info("Complete " + str(__class__) + ": " + sys._getframe().f_code.co_name) - def __str__(self): return "WellBores" def read_parameters(self, model: Model) -> None: """ The read_parameters function reads in the parameters from a dictionary and stores them in the parameters. - It also handles special cases that need to be handled after a value has been read in and checked. - If you choose to subclass this master class, you can also choose to override this method (or not). + It also handles special cases that need to be handled after a value has been read in and checked. + If you choose to subclass this master class, you can also choose to override this method (or not). :param model: The container class of the application, giving access to everything else, including the logger :type model: :class:`~geophires_x.Model.Model` :return: None """ - model.logger.info("Init " + str(__class__) + ": " + sys._getframe().f_code.co_name) + model.logger.info(f"Init {self.__class__.__name__}: {__name__}") - # Deal with all the parameter values that the user has provided. They should really only provide values that + # Deal with all the parameter values that the user has provided. They should really only provide values that # they want to change from the default values, but they can provide a value that is already set because it is a - # default value set in __init__. It will ignore those. + # default value set in __init__. It will ignore those. # This also deals with all the special cases that need to be taken care of after a value has been # read in and checked. # If you choose to subclass this master class, you can also choose to override this method (or not), - # and if you do, do it before or after you call you own version of this method. If you do, you can also choose + # and if you do, do it before or after you call you own version of this method. If you do, you can also choose # to call this method from you class, which can modify all these superclass parameters in your class. if len(model.InputParameters) > 0: @@ -897,9 +879,17 @@ def read_parameters(self, model: Model) -> None: ReadParameter(ParameterReadIn, ParameterToModify, model) # this should handle all non-special cases # handle special cases + # IsAGS is false by default - if it equal 1, then it is true + if ParameterToModify.Name == "Ramey Production Wellbore Model": + if ParameterReadIn.sValue == '0': + ParameterToModify.value = False + # Ramey Production Wellbore Model is true by default - if it equal 0, then it is false + elif ParameterToModify.Name == "Is AGS": + if ParameterReadIn.sValue == '1': + ParameterToModify.value = True # impedance: impedance per well pair (input as GPa*s/m^3 and converted to KPa/kg/s # (assuming 1000 for density; density will be corrected for later)) - if ParameterToModify.Name == "Reservoir Impedance": + elif ParameterToModify.Name == "Reservoir Impedance": # shift it by a constant to make the units right, per line 619 of GEOPHIRES 2 self.impedance.value = self.impedance.value * (1E6 / 1E3) self.impedancemodelused.value = True @@ -917,7 +907,7 @@ def read_parameters(self, model: Model) -> None: self.usebuiltinppwellheadcorrelation = False else: model.logger.info("No parameters read because no content provided") - model.logger.info("read parameters complete " + str(__class__) + ": " + sys._getframe().f_code.co_name) + model.logger.info(f"read parameters complete {self.__class__.__name__}: {__name__}") def Calculate(self, model: Model) -> None: """ @@ -927,7 +917,7 @@ def Calculate(self, model: Model) -> None: :type model: :class:`~geophires_x.Model.Model` :return: Nothing, but it does make calculations and set values in the model """ - model.logger.info("Init " + str(__class__) + ": " + sys._getframe().f_code.co_name) + model.logger.info(f"Init {self.__class__.__name__}: {__name__}") # This is where all the calculations are made using all the values that have been set. # If you subclass this class, you can choose to run these calculations before (or after) your calculations, @@ -1035,4 +1025,4 @@ def Calculate(self, model: Model) -> None: model.surfaceplant.plant_outlet_pressure.value, self.PumpingPowerProd.value) - model.logger.info("complete " + str(__class__) + ": " + sys._getframe().f_code.co_name) + model.logger.info(f"complete {self.__class__.__name__}: {__name__}") diff --git a/src/geophires_x_schema_generator/__init__.py b/src/geophires_x_schema_generator/__init__.py index 0c68bd8f..f89d747e 100644 --- a/src/geophires_x_schema_generator/__init__.py +++ b/src/geophires_x_schema_generator/__init__.py @@ -2,7 +2,7 @@ from typing import Tuple from geophires_x.AGSEconomics import AGSEconomics -from geophires_x.AGSSurfacePlant import AGSSurfacePlant +from geophires_x.SurfacePlantAGS import SurfacePlantAGS from geophires_x.AGSWellBores import AGSWellBores from geophires_x.CylindricalReservoir import CylindricalReservoir from geophires_x.GeoPHIRESUtils import json_dumpse @@ -10,7 +10,7 @@ from geophires_x.Parameter import Parameter from geophires_x.SUTRAEconomics import SUTRAEconomics from geophires_x.SUTRAReservoir import SUTRAReservoir -from geophires_x.SurfacePlantSUTRA import SUTRASurfacePlant +from geophires_x.SurfacePlantSUTRA import SurfacePlantSUTRA from geophires_x.SUTRAWellBores import SUTRAWellBores @@ -36,8 +36,8 @@ def _with_cat(p: Parameter, cat: str): (AGSWellBores(dummy_model), 'Well Bores'), (SUTRAWellBores(dummy_model), 'Well Bores'), (dummy_model.surfaceplant, 'Surface Plant'), - (AGSSurfacePlant(dummy_model), 'Surface Plant'), - (SUTRASurfacePlant(dummy_model), 'Surface Plant'), + (SurfacePlantAGS(dummy_model), 'Surface Plant'), + (SurfacePlantSUTRA(dummy_model), 'Surface Plant'), (dummy_model.economics, 'Economics'), (AGSEconomics(dummy_model), 'Economics'), (SUTRAEconomics(dummy_model), 'Economics'),