Skip to content

Commit

Permalink
added some new parameters and changed the import of Economincs in SBT…
Browse files Browse the repository at this point in the history
… Economics
  • Loading branch information
malcolm-dsider committed Sep 2, 2024
1 parent 69669eb commit 95c37b7
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 27 deletions.
18 changes: 12 additions & 6 deletions src/geophires_x/Economics.py
Original file line number Diff line number Diff line change
Expand Up @@ -1766,8 +1766,14 @@ def __init__(self, model: Model):
PreferredUnits=CurrencyUnit.MDOLLARS,
CurrentUnits=CurrencyUnit.MDOLLARS
)
self.cost_nonvertical_section = self.OutputParameterDict[self.cost_nonvertical_section.Name] = OutputParameter(
Name="Cost of the non-vertical section of a well",
self.cost_lateral_section = self.OutputParameterDict[self.cost_lateral_section.Name] = OutputParameter(
Name="Cost of the entire (multi-) lateral section of a well",
UnitType=Units.CURRENCY,
PreferredUnits=CurrencyUnit.MDOLLARS,
CurrentUnits=CurrencyUnit.MDOLLARS
)
self.cost_to_junction_section = self.OutputParameterDict[self.cost_to_junction_section.Name] = OutputParameter(
Name="Cost of the entire section of a well from bottom of vertical to junction with laterals",
UnitType=Units.CURRENCY,
PreferredUnits=CurrencyUnit.MDOLLARS,
CurrentUnits=CurrencyUnit.MDOLLARS
Expand Down Expand Up @@ -2177,7 +2183,7 @@ def Calculate(self, model: Model) -> None:
(self.cost_one_injection_well.value * model.wellbores.ninj.value))
else:
if hasattr(model.wellbores, 'numnonverticalsections') and model.wellbores.numnonverticalsections.Provided:
self.cost_nonvertical_section.value = 0.0
self.cost_lateral_section.value = 0.0
if not model.wellbores.IsAGS.value:
input_vert_depth_km = model.reserv.depth.quantity().to('km').magnitude
output_vert_depth_km = 0.0
Expand Down Expand Up @@ -2218,20 +2224,20 @@ def Calculate(self, model: Model) -> None:
self.injection_well_cost_adjustment_factor.value)

if hasattr(model.wellbores, 'numnonverticalsections') and model.wellbores.numnonverticalsections.Provided:
self.cost_nonvertical_section.value = calculate_cost_of_non_vertical_section(model, tot_horiz_m,
self.cost_lateral_section.value = calculate_cost_of_non_vertical_section(model, tot_horiz_m,
self.wellcorrelation.value,
self.Nonvertical_drilling_cost_per_m.value,
model.wellbores.numnonverticalsections.value,
self.per_injection_well_cost.Name,
model.wellbores.NonverticalsCased.value,
self.production_well_cost_adjustment_factor.value)
else:
self.cost_nonvertical_section.value = 0.0
self.cost_lateral_section.value = 0.0
# cost of the well field
# 1.05 for 5% indirect costs
self.Cwell.value = 1.05 * ((self.cost_one_production_well.value * model.wellbores.nprod.value) +
(self.cost_one_injection_well.value * model.wellbores.ninj.value) +
self.cost_nonvertical_section.value)
self.cost_lateral_section.value)

# reservoir stimulation costs (M$/injection well). These are calculated whether totalcapcost.Valid = 1
if self.ccstimfixed.Valid:
Expand Down
4 changes: 2 additions & 2 deletions src/geophires_x/Outputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -1788,10 +1788,10 @@ def PrintOutputs(self, model: Model):
model.economics.cost_one_injection_well.value != -1:
f.write(f' Drilling and completion costs per production well: {econ.cost_one_production_well.value:10.2f} ' + econ.cost_one_production_well.CurrentUnits.value + NL)
f.write(f' Drilling and completion costs per injection well: {econ.cost_one_injection_well.value:10.2f} ' + econ.cost_one_injection_well.CurrentUnits.value + NL)
elif econ.cost_nonvertical_section.value > 0.0:
elif econ.cost_lateral_section.value > 0.0:
f.write(f' Drilling and completion costs per vertical production well: {econ.cost_one_production_well.value:10.2f} ' + econ.cost_one_production_well.CurrentUnits.value + NL)
f.write(f' Drilling and completion costs per vertical injection well: {econ.cost_one_injection_well.value:10.2f} ' + econ.cost_one_injection_well.CurrentUnits.value + NL)
f.write(f' Drilling and completion costs per non-vertical sections: {econ.cost_nonvertical_section.value:10.2f} ' + econ.cost_nonvertical_section.CurrentUnits.value + NL)
f.write(f' Drilling and completion costs per non-vertical sections: {econ.cost_lateral_section.value:10.2f} ' + econ.cost_lateral_section.CurrentUnits.value + NL)
else:
f.write(f' Drilling and completion costs per well: {model.economics.Cwell.value/(model.wellbores.nprod.value+model.wellbores.ninj.value):10.2f} ' + model.economics.Cwell.CurrentUnits.value + NL)
f.write(f' Stimulation costs: {model.economics.Cstim.value:10.2f} ' + model.economics.Cstim.CurrentUnits.value + NL)
Expand Down
39 changes: 20 additions & 19 deletions src/geophires_x/SBTEconomics.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import sys, math
import numpy as np
import geophires_x.Model as Model
import geophires_x.Economics as Economics
from .Economics import Economics, calculate_cost_of_one_vertical_well, BuildPTCModel, BuildPricingModel, \
CalculateRevenue, CalculateFinancialPerformance, CalculateLCOELCOHLCOC
from .OptionList import Configuration, WellDrillingCostCorrelation, PlantType
from geophires_x.Parameter import floatParameter
from geophires_x.Units import *
Expand Down Expand Up @@ -124,7 +125,7 @@ def calculate_cost_of_lateral_section(model: Model, length_m: float, well_correl
return cost_of_lateral_section


class SBTEconomics(Economics.Economics):
class SBTEconomics(Economics):
"""
SBTEconomics Child class of Economics; it is the same, but has advanced SBT closed-loop functionality
"""
Expand Down Expand Up @@ -269,7 +270,7 @@ def Calculate(self, model: Model) -> None:
else:
# calculate the cost of one vertical production well
# 1.05 for 5% indirect costs
self.cost_one_production_well.value = 1.05 * Economics.calculate_cost_of_one_vertical_well(model, model.wellbores.vertical_section_length.value,
self.cost_one_production_well.value = 1.05 * calculate_cost_of_one_vertical_well(model, model.wellbores.vertical_section_length.value,
self.wellcorrelation.value,
self.Vertical_drilling_cost_per_m.value,
self.per_production_well_cost.Name,
Expand Down Expand Up @@ -299,7 +300,7 @@ def Calculate(self, model: Model) -> None:
# This section is not vertical, but it is cased, so we will estimate the cost
# of this section as if it were a vertical section.
if model.wellbores.Configuration.value == Configuration.EAVORLOOP:
self.cost_to_junction_section.value = 1.05 * Economics.calculate_cost_of_one_vertical_well(model,
self.cost_to_junction_section.value = 1.05 * calculate_cost_of_one_vertical_well(model,
model.wellbores.tot_to_junction_m.value,
self.wellcorrelation.value,
self.Vertical_drilling_cost_per_m.value,
Expand Down Expand Up @@ -744,32 +745,32 @@ def Calculate(self, model: Model) -> None:
self.PTCCoolingPrice = [0.0] * model.surfaceplant.plant_lifetime.value
self.PTCCarbonPrice = [0.0] * model.surfaceplant.plant_lifetime.value
if self.PTCElec.Provided:
self.PTCElecPrice = Economics.BuildPTCModel(model.surfaceplant.plant_lifetime.value,
self.PTCElecPrice = BuildPTCModel(model.surfaceplant.plant_lifetime.value,
self.PTCDuration.value, self.PTCElec.value, self.PTCInflationAdjusted.value,
self.RINFL.value)
if self.PTCHeat.Provided:
self.PTCHeatPrice = Economics.BuildPTCModel(model.surfaceplant.plant_lifetime.value,
self.PTCHeatPrice = BuildPTCModel(model.surfaceplant.plant_lifetime.value,
self.PTCDuration.value, self.PTCHeat.value, self.PTCInflationAdjusted.value,
self.RINFL.value)
if self.PTCCooling.Provided:
self.PTCCoolingPrice = Economics.BuildPTCModel(model.surfaceplant.plant_lifetime.value,
self.PTCCoolingPrice = BuildPTCModel(model.surfaceplant.plant_lifetime.value,
self.PTCDuration.value, self.PTCCooling.value, self.PTCInflationAdjusted.value,
self.RINFL.value)

# build the price models
self.ElecPrice.value = Economics.BuildPricingModel(model.surfaceplant.plant_lifetime.value,
self.ElecPrice.value = BuildPricingModel(model.surfaceplant.plant_lifetime.value,
self.ElecStartPrice.value, self.ElecEndPrice.value,
self.ElecEscalationStart.value, self.ElecEscalationRate.value,
self.PTCElecPrice)
self.HeatPrice.value = Economics.BuildPricingModel(model.surfaceplant.plant_lifetime.value,
self.HeatPrice.value = BuildPricingModel(model.surfaceplant.plant_lifetime.value,
self.HeatStartPrice.value, self.HeatEndPrice.value,
self.HeatEscalationStart.value, self.HeatEscalationRate.value,
self.PTCHeatPrice)
self.CoolingPrice.value = Economics.BuildPricingModel(model.surfaceplant.plant_lifetime.value,
self.CoolingPrice.value = BuildPricingModel(model.surfaceplant.plant_lifetime.value,
self.CoolingStartPrice.value, self.CoolingEndPrice.value,
self.CoolingEscalationStart.value, self.CoolingEscalationRate.value,
self.PTCCoolingPrice)
self.CarbonPrice.value = Economics.BuildPricingModel(model.surfaceplant.plant_lifetime.value,
self.CarbonPrice.value = BuildPricingModel(model.surfaceplant.plant_lifetime.value,
self.CarbonStartPrice.value, self.CarbonEndPrice.value,
self.CarbonEscalationStart.value, self.CarbonEscalationRate.value,
self.PTCCarbonPrice)
Expand All @@ -796,19 +797,19 @@ def Calculate(self, model: Model) -> None:

# Based on the style of the project, calculate the revenue & cumulative revenue
if model.surfaceplant.enduse_option.value == EndUseOptions.ELECTRICITY:
self.ElecRevenue.value, self.ElecCummRevenue.value = Economics.CalculateRevenue(
self.ElecRevenue.value, self.ElecCummRevenue.value = CalculateRevenue(
model.surfaceplant.plant_lifetime.value, model.surfaceplant.construction_years.value,
model.surfaceplant.NetkWhProduced.value, self.ElecPrice.value)
self.TotalRevenue.value = self.ElecRevenue.value
#self.TotalCummRevenue.value = self.ElecCummRevenue.value
elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value not in [PlantType.ABSORPTION_CHILLER]:
self.HeatRevenue.value, self.HeatCummRevenue.value = Economics.CalculateRevenue(
self.HeatRevenue.value, self.HeatCummRevenue.value = CalculateRevenue(
model.surfaceplant.plant_lifetime.value, model.surfaceplant.construction_years.value,
model.surfaceplant.HeatkWhProduced.value, self.HeatPrice.value)
self.TotalRevenue.value = self.HeatRevenue.value
#self.TotalCummRevenue.value = self.HeatCummRevenue.value
elif model.surfaceplant.enduse_option.value == EndUseOptions.HEAT and model.surfaceplant.plant_type.value in [PlantType.ABSORPTION_CHILLER]:
self.CoolingRevenue.value, self.CoolingCummRevenue.value = Economics.CalculateRevenue(
self.CoolingRevenue.value, self.CoolingCummRevenue.value = CalculateRevenue(
model.surfaceplant.plant_lifetime.value, model.surfaceplant.construction_years.value,
model.surfaceplant.cooling_kWh_Produced.value, self.CoolingPrice.value)
self.TotalRevenue.value = self.CoolingRevenue.value
Expand All @@ -820,10 +821,10 @@ def Calculate(self, model: Model) -> None:
EndUseOptions.COGENERATION_PARALLEL_EXTRA_HEAT,
EndUseOptions.COGENERATION_PARALLEL_EXTRA_ELECTRICITY]: # co-gen
# else:
self.ElecRevenue.value, self.ElecCummRevenue.value = Economics.CalculateRevenue(
self.ElecRevenue.value, self.ElecCummRevenue.value = CalculateRevenue(
model.surfaceplant.plant_lifetime.value, model.surfaceplant.construction_years.value,
model.surfaceplant.NetkWhProduced.value, self.ElecPrice.value)
self.HeatRevenue.value, self.HeatCummRevenue.value = Economics.CalculateRevenue(
self.HeatRevenue.value, self.HeatCummRevenue.value = CalculateRevenue(
model.surfaceplant.plant_lifetime.value, model.surfaceplant.construction_years.value,
model.surfaceplant.HeatkWhProduced.value, self.HeatPrice.value)

Expand All @@ -834,7 +835,7 @@ def Calculate(self, model: Model) -> None:

if self.DoCarbonCalculations.value:
self.CarbonRevenue.value, self.CarbonCummCashFlow.value, self.CarbonThatWouldHaveBeenProducedAnnually.value, \
self.CarbonThatWouldHaveBeenProducedTotal.value = Economics.CalculateCarbonRevenue(model,
self.CarbonThatWouldHaveBeenProducedTotal.value = CalculateCarbonRevenue(model,
model.surfaceplant.plant_lifetime.value, model.surfaceplant.construction_years.value,
self.CarbonPrice.value, self.GridCO2Intensity.value, self.NaturalGasCO2Intensity.value,
model.surfaceplant.NetkWhProduced.value, model.surfaceplant.HeatkWhProduced.value)
Expand Down Expand Up @@ -871,7 +872,7 @@ def Calculate(self, model: Model) -> None:

# Calculate more financial values using numpy financials
self.ProjectNPV.value, self.ProjectIRR.value, self.ProjectVIR.value, self.ProjectMOIC.value = \
Economics.CalculateFinancialPerformance(model.surfaceplant.plant_lifetime.value, self.FixedInternalRate.value,
CalculateFinancialPerformance(model.surfaceplant.plant_lifetime.value, self.FixedInternalRate.value,
self.TotalRevenue.value, self.TotalCummRevenue.value, self.CCap.value,
self.Coam.value)

Expand All @@ -887,7 +888,7 @@ def Calculate(self, model: Model) -> None:


# Calculate LCOE/LCOH
self.LCOE.value, self.LCOH.value, self.LCOC.value = Economics.CalculateLCOELCOHLCOC(self, model)
self.LCOE.value, self.LCOH.value, self.LCOC.value = CalculateLCOELCOHLCOC(self, model)

model.logger.info(f'complete {__class__!s}: {sys._getframe().f_code.co_name}')

1 change: 1 addition & 0 deletions src/geophires_x/SBTReservoir.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ def __init__(self, model: Model):
Max=1.0,
UnitType=Units.PERCENT,
PreferredUnits=PercentUnit.TENTH,
CurrentUnits=PercentUnit.TENTH,
ErrMessage="assume default percent implicit (1.0)",
ToolTipText="Should be between 0 and 1. Most stable is setting it to 1 which results in \
a fully implicit Euler scheme when calculating the fluid temperature at each time step. \
Expand Down

0 comments on commit 95c37b7

Please sign in to comment.