diff --git a/src/geophires_x/SBTEconomics.py b/src/geophires_x/SBTEconomics.py index 3806f9bd..8941c7ab 100644 --- a/src/geophires_x/SBTEconomics.py +++ b/src/geophires_x/SBTEconomics.py @@ -101,67 +101,7 @@ def __init__(self, model: Model): sclass = str(__class__).replace("", "") self.MyPath = os.path.abspath(__file__) - #self.Electricity_rate = None - #self.Discount_rate = None - #self.error = 0 - #self.AverageOPEX_Plant = 0 - #self.OPEX_Plant = 0 - #self.TotalCAPEX = 0 - #self.CAPEX_Surface_Plant = 0 - #self.CAPEX_Drilling = 0 - - # Set up all the Parameters that will be predefined by this class using the different types of parameter classes. - # Setting up includes giving it a name, a default value, The Unit Type (length, volume, temperature, etc.) - # and Unit Name of that value, sets it as required (or not), sets allowable range, - # the error message if that range is exceeded, the ToolTip Text, and the name of the class that created it. - # This includes setting up temporary variables that will be available to all the class but noy read in by user, - # or used for Output - # This also includes all Parameters that are calculated and then published using the Printouts function. - # If you choose to subclass this master class, you can do so before or after you create your own parameters. - # If you do, you can also choose to call this method from you class, which will effectively add - # and set all these parameters to your class. - # NB: inputs we already have ("already have it") need to be set at ReadParameter time so values - # are set at the last possible time - """ - self.O_and_M_cost_plant = self.ParameterDict[self.O_and_M_cost_plant.Name] = floatParameter( - "Operation & Maintenance Cost of Surface Plant", - DefaultValue=0.015, - Min=0.0, - Max=0.2, - UnitType=Units.PERCENT, - PreferredUnits=PercentUnit.TENTH, - CurrentUnits=PercentUnit.TENTH, - Required=True, - ErrMessage="assume default Operation & Maintenance cost of surface plant expressed as fraction of total surface plant capital cost (0.015)" - ) - self.Direct_use_heat_cost_per_kWth = self.ParameterDict[ - self.Direct_use_heat_cost_per_kWth.Name] = floatParameter( - "Capital Cost for Surface Plant for Direct-use System", - DefaultValue=100.0, - Min=0.0, - Max=10000.0, - UnitType=Units.ENERGYCOST, - PreferredUnits=EnergyCostUnit.DOLLARSPERKW, - CurrentUnits=EnergyCostUnit.DOLLARSPERKW, - Required=False, - ErrMessage="assume default Capital cost for surface plant for direct-use system (100 $/kWth)" - ) - self.Power_plant_cost_per_kWe = self.ParameterDict[self.Power_plant_cost_per_kWe.Name] = floatParameter( - "Capital Cost for Power Plant for Electricity Generation", - DefaultValue=3000.0, - Min=0.0, - Max=10000.0, - UnitType=Units.ENERGYCOST, - PreferredUnits=EnergyCostUnit.DOLLARSPERKW, - CurrentUnits=EnergyCostUnit.DOLLARSPERKW, - Required=True, - ErrMessage="assume default Power plant capital cost per kWe (3000 USD/kWe)" - ) - - # results are stored here and in the parent ProducedTemperature array - -""" model.logger.info(f'complete {__class__!s}: {sys._getframe().f_code.co_name}') def __str__(self): @@ -183,10 +123,6 @@ def read_parameters(self, model: Model) -> None: # because the call to the super.readparameters will set all the variables, # including the ones that are specific to this class - # inputs we already have - needs to be set at ReadParameter time so values set at the latest possible time - # self.Discount_rate = model.economics.discountrate.value # same units are GEOPHIRES - # self.Electricity_rate = model.surfaceplant.electricity_cost_to_buy.value # same units are GEOPHIRES - model.logger.info(f'complete {__class__!s}: {sys._getframe().f_code.co_name}') def Calculate(self, model: Model) -> None: @@ -280,269 +216,8 @@ def Calculate(self, model: Model) -> None: self.cost_lateral_section.value + self.cost_to_junction_section.value) self.Cstim.value = self.calculate_stimulation_costs(model).to(self.Cstim.CurrentUnits).magnitude - - # field gathering system costs (M$) - if self.ccgathfixed.Valid: - self.Cgath.value = self.ccgathfixed.value - else: - self.Cgath.value = self.ccgathadjfactor.value * 50 - 6 * np.max( - model.surfaceplant.HeatExtracted.value) * 1000. # (GEOPHIRES v1 correlation) - if model.wellbores.impedancemodelused.value: - pumphp = np.max(model.wellbores.PumpingPower.value) * 1341 - numberofpumps = np.ceil(pumphp / 2000) # pump can be maximum 2,000 hp - if numberofpumps == 0: - self.Cpumps = 0.0 - else: - pumphpcorrected = pumphp / numberofpumps - self.Cpumps = numberofpumps * 1.5 * ( - (1750 * pumphpcorrected ** 0.7) * 3 * pumphpcorrected ** (-0.11)) - else: - if model.wellbores.productionwellpumping.value: - prodpumphp = np.max(model.wellbores.PumpingPowerProd.value) / model.wellbores.nprod.value * 1341 - Cpumpsprod = model.wellbores.nprod.value * 1.5 * (1750 * prodpumphp ** 0.7 + 5750 * - prodpumphp ** 0.2 + 10000 + np.max( - model.wellbores.pumpdepth.value) * 50 * 3.281) # see page 46 in user's manual assuming rental of rig for 1 day. - else: - Cpumpsprod = 0 - - injpumphp = np.max(model.wellbores.PumpingPowerInj.value) * 1341 - numberofinjpumps = np.ceil(injpumphp / 2000) # pump can be maximum 2,000 hp - if numberofinjpumps == 0: - Cpumpsinj = 0 - else: - injpumphpcorrected = injpumphp / numberofinjpumps - Cpumpsinj = numberofinjpumps * 1.5 * ( - 1750 * injpumphpcorrected ** 0.7) * 3 * injpumphpcorrected ** (-0.11) - self.Cpumps = Cpumpsinj + Cpumpsprod - - # Based on GETEM 2016 #1.15 for 15% contingency - self.Cgath.value = 1.15 * self.ccgathadjfactor.value * self._indirect_cost_factor * ( - (model.wellbores.nprod.value + model.wellbores.ninj.value) * 750 * 500. + self.Cpumps) / 1E6 - - # plant costs - 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: - self.Cplant.value = self._indirect_cost_factor * 1.15 * self.ccplantadjfactor.value * 250E-6 * np.max( - model.surfaceplant.HeatExtracted.value) * 1000. # 1.15 for 15% contingency - - # 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: - # this is for the direct-use part all the way up to the absorption chiller - self.Cplant.value = self._indirect_cost_factor * 1.15 * self.ccplantadjfactor.value * 250E-6 * np.max( - model.surfaceplant.HeatExtracted.value) * 1000. # 1.15 for 15% contingency - if self.chillercapex.value == -1: # no value provided by user, use built-in correlation ($2500/ton) - self.chillercapex.value = self._indirect_cost_factor * 1.15 * np.max( - model.surfaceplant.cooling_produced.value) * 1000 / 3.517 * 2500 / 1e6 # $2,500/ton of cooling. 1.15 for 15% contingency - - # now add chiller cost to surface plant cost - self.Cplant.value += self.chillercapex.value - - # 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: - # this is for the direct-use part all the way up to the heat pump - self.Cplant.value = self._indirect_cost_factor * 1.15 * self.ccplantadjfactor.value * 250E-6 * np.max( - model.surfaceplant.HeatExtracted.value) * 1000. # 1.15 for 15% contingency - if self.heatpumpcapex.value == -1: # no value provided by user, use built-in correlation ($150/kWth) - self.heatpumpcapex.value = self._indirect_cost_factor * 1.15 * np.max( - model.surfaceplant.HeatProduced.value) * 1000 * 150 / 1e6 # $150/kW. 1.15 for 15% contingency - - # now add heat pump cost to surface plant cost - self.Cplant.value += self.heatpumpcapex.value - - # 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: - self.Cplant.value = self._indirect_cost_factor * 1.15 * self.ccplantadjfactor.value * 250E-6 * np.max( - model.surfaceplant.HeatExtracted.value) * 1000. # 1.15 for 15% contingency - - self.peakingboilercost.value = (self.peaking_boiler_cost_per_kW.quantity() - .to('USD / kilowatt').magnitude - * model.surfaceplant.max_peaking_boiler_demand.value - / 1000) - - self.Cplant.value += self.peakingboilercost.value # add peaking boiler cost to surface plant cost - - - else: # all other options have power plant - if model.surfaceplant.plant_type.value == PlantType.SUB_CRITICAL_ORC: - MaxProducedTemperature = np.max(model.surfaceplant.TenteringPP.value) - if MaxProducedTemperature < 150.: - C3 = -1.458333E-3 - C2 = 7.6875E-1 - C1 = -1.347917E2 - C0 = 1.0075E4 - CCAPP1 = C3 * MaxProducedTemperature ** 3 + C2 * MaxProducedTemperature ** 2 + C1 * MaxProducedTemperature + C0 - else: - CCAPP1 = 2231 - 2 * (MaxProducedTemperature - 150.) - x = np.max(model.surfaceplant.ElectricityProduced.value) - y = np.max(model.surfaceplant.ElectricityProduced.value) - if y == 0.0: - y = 15.0 - z = math.pow(y / 15., -0.06) - self.Cplantcorrelation = CCAPP1 * z * x * 1000. / 1E6 - - elif model.surfaceplant.plant_type.value == PlantType.SUPER_CRITICAL_ORC: - MaxProducedTemperature = np.max(model.surfaceplant.TenteringPP.value) - if MaxProducedTemperature < 150.: - C3 = -1.458333E-3 - C2 = 7.6875E-1 - C1 = -1.347917E2 - C0 = 1.0075E4 - CCAPP1 = C3 * MaxProducedTemperature ** 3 + C2 * MaxProducedTemperature ** 2 + C1 * MaxProducedTemperature + C0 - else: - CCAPP1 = 2231 - 2 * (MaxProducedTemperature - 150.) - # factor 1.1 to make supercritical 10% more expansive than subcritical - self.Cplantcorrelation = 1.1 * CCAPP1 * math.pow( - np.max(model.surfaceplant.ElectricityProduced.value) / 15., -0.06) * np.max( - model.surfaceplant.ElectricityProduced.value) * 1000. / 1E6 - - elif model.surfaceplant.plant_type.value == PlantType.SINGLE_FLASH: - if np.max(model.surfaceplant.ElectricityProduced.value) < 10.: - C2 = 4.8472E-2 - C1 = -35.2186 - C0 = 8.4474E3 - D2 = 4.0604E-2 - D1 = -29.3817 - D0 = 6.9911E3 - PLL = 5. - PRL = 10. - elif np.max(model.surfaceplant.ElectricityProduced.value) < 25.: - C2 = 4.0604E-2 - C1 = -29.3817 - C0 = 6.9911E3 - D2 = 3.2773E-2 - D1 = -23.5519 - D0 = 5.5263E3 - PLL = 10. - PRL = 25. - elif np.max(model.surfaceplant.ElectricityProduced.value) < 50.: - C2 = 3.2773E-2 - C1 = -23.5519 - C0 = 5.5263E3 - D2 = 3.4716E-2 - D1 = -23.8139 - D0 = 5.1787E3 - PLL = 25. - PRL = 50. - elif np.max(model.surfaceplant.ElectricityProduced.value) < 75.: - C2 = 3.4716E-2 - C1 = -23.8139 - C0 = 5.1787E3 - D2 = 3.5271E-2 - D1 = -24.3962 - D0 = 5.1972E3 - PLL = 50. - PRL = 75. - else: - C2 = 3.5271E-2 - C1 = -24.3962 - C0 = 5.1972E3 - D2 = 3.3908E-2 - D1 = -23.4890 - D0 = 5.0238E3 - PLL = 75. - PRL = 100. - maxProdTemp = np.max(model.surfaceplant.TenteringPP.value) - CCAPPLL = C2 * maxProdTemp ** 2 + C1 * maxProdTemp + C0 - CCAPPRL = D2 * maxProdTemp ** 2 + D1 * maxProdTemp + D0 - b = math.log(CCAPPRL / CCAPPLL) / math.log(PRL / PLL) - a = CCAPPRL / PRL ** b - # factor 0.75 to make double flash 25% more expansive than single flash - self.Cplantcorrelation = (0.8 * a * math.pow(np.max(model.surfaceplant.ElectricityProduced.value), b) * - np.max(model.surfaceplant.ElectricityProduced.value) * 1000. / 1E6) - - elif model.surfaceplant.plant_type.value == PlantType.DOUBLE_FLASH: - if np.max(model.surfaceplant.ElectricityProduced.value) < 10.: - C2 = 4.8472E-2 - C1 = -35.2186 - C0 = 8.4474E3 - D2 = 4.0604E-2 - D1 = -29.3817 - D0 = 6.9911E3 - PLL = 5. - PRL = 10. - elif np.max(model.surfaceplant.ElectricityProduced.value) < 25.: - C2 = 4.0604E-2 - C1 = -29.3817 - C0 = 6.9911E3 - D2 = 3.2773E-2 - D1 = -23.5519 - D0 = 5.5263E3 - PLL = 10. - PRL = 25. - elif np.max(model.surfaceplant.ElectricityProduced.value) < 50.: - C2 = 3.2773E-2 - C1 = -23.5519 - C0 = 5.5263E3 - D2 = 3.4716E-2 - D1 = -23.8139 - D0 = 5.1787E3 - PLL = 25. - PRL = 50. - elif np.max(model.surfaceplant.ElectricityProduced.value) < 75.: - C2 = 3.4716E-2 - C1 = -23.8139 - C0 = 5.1787E3 - D2 = 3.5271E-2 - D1 = -24.3962 - D0 = 5.1972E3 - PLL = 50. - PRL = 75. - else: - C2 = 3.5271E-2 - C1 = -24.3962 - C0 = 5.1972E3 - D2 = 3.3908E-2 - D1 = -23.4890 - D0 = 5.0238E3 - PLL = 75. - PRL = 100. - maxProdTemp = np.max(model.surfaceplant.TenteringPP.value) - CCAPPLL = C2 * maxProdTemp ** 2 + C1 * maxProdTemp + C0 - CCAPPRL = D2 * maxProdTemp ** 2 + D1 * maxProdTemp + D0 - b = math.log(CCAPPRL / CCAPPLL) / math.log(PRL / PLL) - a = CCAPPRL / PRL ** b - self.Cplantcorrelation = (a * math.pow(np.max(model.surfaceplant.ElectricityProduced.value), b) * - np.max(model.surfaceplant.ElectricityProduced.value) * 1000. / 1E6) - - if self.ccplantfixed.Valid: - self.Cplant.value = self.ccplantfixed.value - self.CAPEX_cost_electricity_plant = self.Cplant.value * self.CAPEX_heat_electricity_plant_ratio.value - self.CAPEX_cost_heat_plant = self.Cplant.value * (1.0 - self.CAPEX_heat_electricity_plant_ratio.value) - else: - # 1.02 to convert cost from 2012 to 2016 #factor 1.15 for 15% contingency and factor 1.10 to convert from 2016 to 2022 - self.Cplant.value = self._indirect_cost_factor * 1.15 * self.ccplantadjfactor.value * self.Cplantcorrelation * 1.02 * 1.10 - self.CAPEX_cost_electricity_plant = self.Cplant.value - - # add direct-use plant cost of co-gen system to Cplant (only of no total Cplant was provided) - if not self.ccplantfixed.Valid: # 1.15 below for contingency - if model.surfaceplant.enduse_option.value in [EndUseOptions.COGENERATION_TOPPING_EXTRA_ELECTRICITY, - EndUseOptions.COGENERATION_TOPPING_EXTRA_HEAT]: # enduse_option = 3: cogen topping cycle - self.CAPEX_cost_heat_plant = self._indirect_cost_factor * 1.15 * self.ccplantadjfactor.value * 250E-6 * np.max( - model.surfaceplant.HeatProduced.value / model.surfaceplant.enduse_efficiency_factor.value) * 1000. - elif model.surfaceplant.enduse_option.value in [EndUseOptions.COGENERATION_BOTTOMING_EXTRA_HEAT, - EndUseOptions.COGENERATION_BOTTOMING_EXTRA_ELECTRICITY]: # enduse_option = 4: cogen bottoming cycle - self.CAPEX_cost_heat_plant = self._indirect_cost_factor * 1.15 * self.ccplantadjfactor.value * 250E-6 * np.max( - model.surfaceplant.HeatProduced.value / model.surfaceplant.enduse_efficiency_factor.value) * 1000. - elif model.surfaceplant.enduse_option.value in [EndUseOptions.COGENERATION_PARALLEL_EXTRA_ELECTRICITY, - EndUseOptions.COGENERATION_PARALLEL_EXTRA_HEAT]: # cogen parallel cycle - self.CAPEX_cost_heat_plant = self._indirect_cost_factor * 1.15 * self.ccplantadjfactor.value * 250E-6 * np.max( - model.surfaceplant.HeatProduced.value / model.surfaceplant.enduse_efficiency_factor.value) * 1000. - - self.Cplant.value = self.Cplant.value + self.CAPEX_cost_heat_plant - if not self.CAPEX_heat_electricity_plant_ratio.Provided: - self.CAPEX_heat_electricity_plant_ratio.value = self.CAPEX_cost_electricity_plant/self.Cplant.value + self.calculate_field_gathering_costs(model) + self.calculate_plant_costs(model) if not self.totalcapcost.Valid: # exploration costs (same as in Geophires v1.2) (M$) diff --git a/src/geophires_x/SUTRAEconomics.py b/src/geophires_x/SUTRAEconomics.py index dbe8f9f5..531b9510 100644 --- a/src/geophires_x/SUTRAEconomics.py +++ b/src/geophires_x/SUTRAEconomics.py @@ -14,194 +14,9 @@ class SUTRAEconomics(Economics.Economics): """ def __init__(self, model: 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 that can be overridden - by user input. - The __init__ function is used to set up all the parameters in Economics. - :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(f'Init {str(__class__)}: {sys._getframe().f_code.co_name}') super().__init__(model) - # Set up all the Parameters that will be predefined by this class using the different types of parameter classes. - # Setting up includes giving it a name, a default value, The Unit Type (length, volume, temperature, etc.) and - # Unit Name of that value, sets it as required (or not), sets allowable range, the error message if that range - # is exceeded, the ToolTip Text, and the name of teh class that created it. - # This includes setting up temporary variables that will be available to all the class but noy read in by user, - # or used for Output - # This also includes all Parameters that are calculated and then published using the Printouts function. - # If you choose to subclass this master class, you can do so before or after you create your own parameters. - # If you do, you can also choose to call this method from you class, which will effectively add and set all - # these parameters to your class. - - # These dictionaries contain a list of all the parameters set in this object, stored as "Parameter" and - # "OutputParameter" Objects. This will allow us later to access them in a user interface and get that list, - # along with unit type, preferred units, etc. - self.ParameterDict = {} - self.OutputParameterDict = {} - - # Note: setting Valid to False for any of the cost parameters forces GEOPHIRES to use it's builtin cost engine. - # This is the default. - self.econmodel = self.ParameterDict[self.econmodel.Name] = intParameter( - "Economic Model", - value=EconomicModel.STANDARDIZED_LEVELIZED_COST, - DefaultValue=EconomicModel.STANDARDIZED_LEVELIZED_COST, - ValuesEnum=EconomicModel, - AllowableRange=[1, 2, 3], - Required=True, - ErrMessage="assume default economic model (2)", - ToolTipText="Specify the economic model to calculate the levelized cost of energy. " + - '; '.join([f'{it.int_value}: {it.value}' for it in EconomicModel]) - ) - - self.ccwellfixed = self.ParameterDict[self.ccwellfixed.Name] = floatParameter( - "Well Drilling and Completion Capital Cost", - value=-1.0, - DefaultValue=-1.0, - Min=0, - Max=200, - UnitType=Units.CURRENCY, - PreferredUnits=CurrencyUnit.MDOLLARS, - CurrentUnits=CurrencyUnit.MDOLLARS, - Provided=False, - Valid=False, - ToolTipText="Well Drilling and Completion Capital Cost", - ) - self.ccwelladjfactor = self.ParameterDict[self.ccwelladjfactor.Name] = floatParameter( - "Well Drilling and Completion Capital Cost Adjustment Factor", - value=1.0, - DefaultValue=1.0, - Min=0, - Max=10, - UnitType=Units.PERCENT, - PreferredUnits=PercentUnit.TENTH, - CurrentUnits=PercentUnit.TENTH, - Provided=False, - Valid=True, - ToolTipText="Well Drilling and Completion Capital Cost Adjustment Factor", - ) - - self.ccplantfixed = self.ParameterDict[self.ccplantfixed.Name] = floatParameter( - "Surface Plant Capital Cost", - value=-1.0, - DefaultValue=-1.0, - Min=0, - Max=1000, - UnitType=Units.CURRENCY, - PreferredUnits=CurrencyUnit.MDOLLARS, - CurrentUnits=CurrencyUnit.MDOLLARS, - Provided=False, - Valid=False, - ToolTipText="Total surface plant capital cost", - ) - self.ccplantadjfactor = self.ParameterDict[self.ccplantadjfactor.Name] = floatParameter( - "Surface Plant Capital Cost Adjustment Factor", - value=1.0, - DefaultValue=1.0, - Min=0, - Max=10, - UnitType=Units.PERCENT, - PreferredUnits=PercentUnit.TENTH, - CurrentUnits=PercentUnit.TENTH, - Provided=False, - Valid=True, - ToolTipText="Multiplier for built-in surface plant capital cost correlation", - ) - - self.inflrateconstruction = self.ParameterDict[self.inflrateconstruction.Name] = floatParameter( - "Inflation Rate During Construction", - value=0.0, - DefaultValue=0.0, - Min=0.0, - Max=1.0, - UnitType=Units.PERCENT, - PreferredUnits=PercentUnit.PERCENT, - CurrentUnits=PercentUnit.TENTH, - ErrMessage="assume default inflation rate during construction (0)", - ) - self.wellcorrelation = self.ParameterDict[self.wellcorrelation.Name] = intParameter( - "Well Drilling Cost Correlation", - DefaultValue=WellDrillingCostCorrelation.VERTICAL_LARGE_INT1.int_value, - AllowableRange=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17], - ValuesEnum=WellDrillingCostCorrelation, - UnitType=Units.NONE, - ErrMessage="assume default well drilling cost correlation (10)", - ToolTipText="Select the built-in well drilling and completion cost correlation: " + - '; '.join([f'{it.int_value}: {it.value}' for it in WellDrillingCostCorrelation]) - ) - - self.timestepsperyear = self.ParameterDict[self.timestepsperyear.Name] = intParameter( - "Time steps per year", - value=4, - DefaultValue=4, - AllowableRange=list(range(1, 101, 1)), - UnitType=Units.NONE, - Required=True, - ErrMessage="assume default number of time steps per year (4)", - ToolTipText="Number of internal simulation time steps per year", - ) - - self.DoAddOnCalculations = self.ParameterDict[self.DoAddOnCalculations.Name] = boolParameter( - "Do AddOn Calculations", - value=False, - DefaultValue=False, - UnitType=Units.NONE, - Required=False, - ErrMessage="assume default: no economics calculations", - ToolTipText="Set to true if you want the add-on economics calculations to be made", - ) - self.DoSDACGTCalculations = self.ParameterDict[self.DoSDACGTCalculations.Name] = boolParameter( - "Do S-DAC-GT Calculations", - value=False, - DefaultValue=False, - UnitType=Units.NONE, - Required=False, - ErrMessage="assume default: no S-DAC-GT calculations", - ToolTipText="Set to true if you want the S-DAC-GT economics calculations to be made", - ) - - # heat pump - self.heatpumpcapex = self.ParameterDict[self.heatpumpcapex.Name] = floatParameter( - "Heat Pump Capital Cost", - value=-1.0, - Min=0, - Max=100, - UnitType=Units.CURRENCY, - PreferredUnits=CurrencyUnit.MDOLLARS, - CurrentUnits=CurrencyUnit.MDOLLARS, - Provided=False, - Valid=False, - ToolTipText="Heat pump capital cost", - ) - - self.ngprice = self.ParameterDict[self.ngprice.Name] = floatParameter( - "Peaking Fuel Cost Rate", - value=0.034, - Min=0.0, - Max=1.0, - UnitType=Units.ENERGYCOST, - PreferredUnits=EnergyCostUnit.DOLLARSPERKWH, - CurrentUnits=EnergyCostUnit.DOLLARSPERKWH, - ErrMessage="assume default peaking fuel rate ($0.034/kWh)", - ToolTipText="Price of peaking fuel for peaking boilers", - ) - self.peakingboilerefficiency = self.ParameterDict[self.peakingboilerefficiency.Name] = floatParameter( - "Peaking Boiler Efficiency", - value=0.85, - Min=0, - Max=1, - UnitType=Units.PERCENT, - PreferredUnits=PercentUnit.TENTH, - CurrentUnits=PercentUnit.TENTH, - Provided=False, - Valid=False, - ErrMessage="assume default peaking boiler efficiency (85%)", - ToolTipText="Peaking boiler efficiency", - ) - self.LCOH = self.OutputParameterDict[self.LCOH.Name] = OutputParameter( "Heat Sale Price Model", display_name='Direct-Use heat breakeven price (LCOH)', @@ -219,22 +34,6 @@ def __init__(self, model: Model): self.MyClass = sclass.replace("\'>", "") self.MyPath = os.path.abspath(__file__) - # results - self.Cwell = self.OutputParameterDict[self.Cwell.Name] = OutputParameter( - Name="Wellfield cost", - value=-999.9, - UnitType=Units.CURRENCY, - PreferredUnits=CurrencyUnit.MDOLLARS, - CurrentUnits=CurrencyUnit.MDOLLARS, - ) - - 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, @@ -249,26 +48,6 @@ def __init__(self, model: Model): PreferredUnits=CurrencyFrequencyUnit.KDOLLARSPERYEAR, CurrentUnits=CurrencyFrequencyUnit.KDOLLARSPERYEAR, ) - - # heat pump - 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, - ) - - self.peakingboilercost = self.OutputParameterDict[self.peakingboilercost.Name] = OutputParameter( - Name="Peaking boiler cost", - value=0, - UnitType=Units.CURRENCY, - PreferredUnits=CurrencyUnit.MDOLLARS, - CurrentUnits=CurrencyUnit.MDOLLARS, - ) - self.annualngcost = self.OutputParameterDict[self.annualngcost.Name] = OutputParameter( Name="Annual Peaking Fuel Cost", value=0, @@ -347,7 +126,7 @@ def Calculate(self, model: Model) -> None: # Drilling self.C1well = 0 - if self.ccwellfixed.Valid: + if self.per_production_well_cost.Valid: self.C1well = self.ccwellfixed.value self.Cwell.value = self.C1well * (model.wellbores.nprod.value + model.wellbores.ninj.value) else: @@ -359,13 +138,16 @@ def Calculate(self, model: Model) -> None: self.C1well = self.wellcorrelation.value.calculate_cost_MUSD(model.reserv.depth.value) - self.C1well = self.C1well * self.ccwelladjfactor.value + self.C1well = self.C1well * self.production_well_cost_adjustment_factor.value self.Cwell.value = self.C1well * (model.wellbores.nprod.value + model.wellbores.ninj.value) # Boiler self.peakingboilercost.value = ( - 65 * model.surfaceplant.max_peaking_boiler_demand.value / self.peakingboilerefficiency.value / 1000 - ) # add 65$/KW for peaking boiler + self.peaking_boiler_cost_per_kW.quantity().to('USD/kW').magnitude + * model.surfaceplant.max_peaking_boiler_demand.value + / self.peakingboilerefficiency.value + / 1000 + ) # Circulation Pump pumphp = np.max(model.wellbores.PumpingPower.value) * 1.341