@@ -625,7 +625,8 @@ def __init__(self, model: Model):
625625 CurrentUnits = CurrencyUnit .MDOLLARS ,
626626 Provided = False ,
627627 Valid = False ,
628- ToolTipText = "Total reservoir stimulation capital cost, including indirect costs and contingency."
628+ ToolTipText = 'Total reservoir stimulation capital cost, including indirect costs and contingency. '
629+ f'For traditional hydrothermal reservoirs, this parameter should be set to $0.'
629630 )
630631
631632 max_stimulation_cost_per_well_MUSD = 100
@@ -938,7 +939,18 @@ def __init__(self, model: Model):
938939 UnitType = Units .NONE ,
939940 Required = True ,
940941 ErrMessage = "assume default number of time steps per year (4)" ,
941- ToolTipText = "Number of internal simulation time steps per year"
942+ ToolTipText = 'Number of internal simulation time steps per year. GEOPHIRES assumes linear time '
943+ 'discretization with a user-provided number of time steps per year over the lifetime of the '
944+ 'plant. The default is four time steps per year, meaning a time step of 3 months. '
945+ 'At every time step, GEOPHIRES calculates the reservoir output temperature, production '
946+ 'wellhead temperature, direct-use heat and/or electricity power output (in MW), pressure '
947+ 'drops and pumping power. On an annual basis, GEOPHIRES calculates the O&M costs and '
948+ 'direct-use heat and/or electricity production. To investigate seasonal effects, e.g., to '
949+ 'assess the impact of more geothermal heat demand for district heating in winter than in '
950+ 'summer, the user can select a smaller time step, e.g., a month (or 12 time steps per year). '
951+ 'For even shorter timescale effects, e.g., to account for an hourly varying ambient '
952+ 'temperature or investigate the response in plant operation to a fluctuating revenue rate), '
953+ 'the user can select an even smaller time step, e.g., 1 h (or 8760 time steps per year).'
942954 )
943955 self .FCR = self .ParameterDict [self .FCR .Name ] = floatParameter (
944956 "Fixed Charge Rate" ,
@@ -1824,22 +1836,28 @@ def __init__(self, model: Model):
18241836 f'costs per well. '
18251837 f'Provide { self .ccstimadjfactor .Name } to multiply the correlation-calculated cost. '
18261838 f'Provide { self .ccstimfixed .Name } to override the correlation and set your own '
1827- f'total stimulation cost.'
1839+ f'total stimulation cost. '
1840+ f'For traditional hydrothermal reservoirs, { self .ccstimfixed .Name } should be set to $0.'
18281841 )
18291842
1830- contingency_and_indirect_costs_tooltip = (
1831- f'plus { self .contingency_percentage .quantity ().to (convertible_unit ("%" )).magnitude :g} % contingency '
1843+ # TODO switch order to align with theoretical basis, which lists indirect costs first
1844+ contingency_and_indirect_costs_tooltip_stem = (
1845+ f'{ self .contingency_percentage .quantity ().to (convertible_unit ("%" )).magnitude :g} % contingency '
18321846 f'plus { self .indirect_capital_cost_percentage .quantity ().to (convertible_unit ("%" )).magnitude } % '
18331847 f'indirect costs'
18341848 )
1849+ contingency_and_indirect_costs_tooltip = (
1850+ f'plus { contingency_and_indirect_costs_tooltip_stem } '
1851+ )
18351852
18361853 self .Cexpl = self .OutputParameterDict [self .Cexpl .Name ] = OutputParameter (
18371854 Name = "Exploration cost" ,
18381855 display_name = 'Exploration costs' ,
18391856 UnitType = Units .CURRENCY ,
18401857 PreferredUnits = CurrencyUnit .MDOLLARS ,
18411858 CurrentUnits = CurrencyUnit .MDOLLARS ,
1842- ToolTipText = f'Default correlation: 60% of the cost of one production well '
1859+ ToolTipText = f'The built-in exploration cost correlation considers drilling of a slim-hole well at 60% of '
1860+ f'the cost of a regular well, $1M for geophysical and field work, '
18431861 f'{ contingency_and_indirect_costs_tooltip } . '
18441862 f'Provide { self .ccexpladjfactor .Name } to multiply the default correlation. '
18451863 f'Provide { self .ccexplfixed .Name } to override the default correlation and set your own cost.'
@@ -1865,14 +1883,21 @@ def __init__(self, model: Model):
18651883 ToolTipText = 'Drilling and completion cost per well, including indirect costs '
18661884 f'(default: { self .wellfield_indirect_capital_cost_percentage .DefaultValue } %).'
18671885 )
1886+
1887+ # noinspection SpellCheckingInspection
18681888 self .Coamwell = self .OutputParameterDict [self .Coamwell .Name ] = OutputParameter (
18691889 Name = "O&M Wellfield cost" ,
18701890 display_name = 'Wellfield maintenance costs' ,
18711891 UnitType = Units .CURRENCYFREQUENCY ,
18721892 PreferredUnits = CurrencyFrequencyUnit .MDOLLARSPERYEAR ,
1873- CurrentUnits = CurrencyFrequencyUnit .MDOLLARSPERYEAR
1874- # TODO TooltipText to document how this is calculated
1893+ CurrentUnits = CurrencyFrequencyUnit .MDOLLARSPERYEAR ,
1894+ # TODO parameterize relevant constants in tooltip text
1895+ ToolTipText = 'The built-in correlation for the wellfield O&M costs is similar as the surface plant O&M '
1896+ 'costs: it assumes that it consists of 1% of the total wellfield plus field gathering system '
1897+ 'costs (for annual non-labor costs) and 25% of the labor costs (the other 75% of the labor '
1898+ 'costs are assigned to the surface plant O&M costs).'
18751899 )
1900+
18761901 self .redrilling_annual_cost = self .OutputParameterDict [self .redrilling_annual_cost .Name ] = OutputParameter (
18771902 Name = "Redrilling costs" ,
18781903 UnitType = Units .CURRENCYFREQUENCY ,
@@ -1884,25 +1909,85 @@ def __init__(self, model: Model):
18841909 f'The total is then divided over { model .surfaceplant .plant_lifetime .Name } years to calculate '
18851910 f'Redrilling costs per year.'
18861911 )
1912+ # noinspection SpellCheckingInspection
18871913 self .Cplant = self .OutputParameterDict [self .Cplant .Name ] = OutputParameter (
18881914 Name = "Surface Plant cost" ,
1915+ display_name = 'Surface power plant costs' ,
18891916 UnitType = Units .CURRENCY ,
18901917 PreferredUnits = CurrencyUnit .MDOLLARS ,
1891- CurrentUnits = CurrencyUnit .MDOLLARS
1918+ CurrentUnits = CurrencyUnit .MDOLLARS ,
1919+ # TODO incorporate direct references to relevant parameters for adjusting correlation in tooltip text
1920+ # TODO interpolate relevant constants (that are currently hardcoded) in tooltip text
1921+ ToolTipText = 'The built-in power plant cost correlations are based on the original correlations developed '
1922+ 'by Beckers (2016), indexed to 2017 using the IHS Markit North American Power Capital Costs '
1923+ 'Index (NAPCCI) excluding nuclear plants (IHS 2018). The ORC power plant cost data have been '
1924+ 'updated with data from the 2016 GETEM tool (DOE 2016) and the geothermal binary power plants '
1925+ 'study by Verkis (2014). '
1926+ # Note: actual author name above is "Verkís" but the unicode accented i may cause unexpected
1927+ # problems in consumers.
1928+ 'Figure 4 in the Theoretical Basis shows the power plant capital cost expressed in $ kWe-1 '
1929+ 'as a function of plant size and initial production temperature for subcritical ORC and '
1930+ 'double-flash power plants. '
1931+ f'The default correlations in GEOPHIRES include { contingency_and_indirect_costs_tooltip_stem } . '
1932+ 'For the same plant size and production temperature, double-flash power plants are considered '
1933+ 'about 25% more expensive than single-flash power plants (Zeyghami 2010), and supercritical '
1934+ 'ORC plants are roughly 10% more than subcritical ORC plants (Astolfi et al. 2014). A wide '
1935+ 'range in power plant specific cost values is reported in academic and popular literature. '
1936+ 'The GEOPHIRES built-in surface plant cost correlations represent typical values. However, '
1937+ 'the user is recommended to provide their own power plant cost data if available for their '
1938+ 'case study. The ORC plant specific cost decreases only moderately at higher temperatures. '
1939+ 'The reasons are that when increasing the temperature, the ORC plant design also changes: '
1940+ '(1) a different organic fluid is selected, (2) piping, pump, heat exchangers, and other '
1941+ 'equipment are designed to handle the higher temperature (and potentially also pressure), '
1942+ 'requiring thicker walls, potentially different materials, etc., and (3) additional components '
1943+ 'may be implemented, such as a heat recuperator, making the design and operation more complex. '
1944+ 'Unlike flash power plants, ORC plants are a small, niche market, typically case specific, '
1945+ 'and rely on relatively young technology, which has not been subject yet to decades of '
1946+ 'technological advancement. The cost for direct-use heat applications is highly dependent '
1947+ 'on the type of application. A generic cost of $250 kWth-1 is assumed '
1948+ f'{ contingency_and_indirect_costs_tooltip } . '
1949+ 'However, users are encouraged to provide their own cost figures for '
1950+ 'their specific application. Beckers and Young (2017) collected several cost figures to '
1951+ 'estimate the surface equipment cost for geothermal district-heating systems.'
18921952 )
18931953 self .Coamplant = self .OutputParameterDict [self .Coamplant .Name ] = OutputParameter (
18941954 Name = "O&M Surface Plant costs" ,
18951955 display_name = 'Power plant maintenance costs' ,
18961956 UnitType = Units .CURRENCYFREQUENCY ,
18971957 PreferredUnits = CurrencyFrequencyUnit .MDOLLARSPERYEAR ,
1898- CurrentUnits = CurrencyFrequencyUnit .MDOLLARSPERYEAR
1958+ CurrentUnits = CurrencyFrequencyUnit .MDOLLARSPERYEAR ,
1959+ # TODO parameterize relevant constants in tooltip text
1960+ # TODO update index year and/or make indexing parameterizable in tooltip text
1961+ ToolTipText = 'GEOPHIRES estimates the annual surface plant O&M costs as the sum of 1.5% of the total plant '
1962+ 'capital cost (for annual non-labor costs), and 75% of the annual labor costs. The other 25% '
1963+ 'of the labor costs are assigned to the wellfield O&M cost. The labor costs are calculated '
1964+ 'internally in GEOPHIRES using the 2014 labor costs provided by Beckers (2016), indexed to '
1965+ '2017 using the Bureau of Labor Statistics (BLS) Employment Cost Index for utilities (2018). '
1966+ 'The original 2014 labor cost correlation expresses the labor costs as a function of the plant '
1967+ 'size (MW) using an approximate logarithmic curve fit to the built-in labor cost data in '
1968+ 'GETEM.'
18991969 )
1970+ # noinspection SpellCheckingInspection
19001971 self .Cgath = self .OutputParameterDict [self .Cgath .Name ] = OutputParameter (
19011972 Name = "Field gathering system cost" ,
19021973 display_name = 'Field gathering system costs' ,
19031974 UnitType = Units .CURRENCY ,
19041975 PreferredUnits = CurrencyUnit .MDOLLARS ,
1905- CurrentUnits = CurrencyUnit .MDOLLARS
1976+ CurrentUnits = CurrencyUnit .MDOLLARS ,
1977+ # TODO interpolate constant values in tooltip text instead of hardcoding in tooltip text
1978+ ToolTipText = 'The built-in cost correlation for estimating the field gathering system cost includes '
1979+ 'the cost for surface piping from each well to the plant and pumps for production and '
1980+ 'injection wells. The length of the surface piping is assumed 750 m per well at a cost of '
1981+ '$500 per meter. The pumping cost for each pump in the production wells (line-shaft pumps) '
1982+ 'and a single pump for the injection wells is calculated with the same correlation as GETEM. '
1983+ f'Contingency (default: '
1984+ f'{ self .contingency_percentage .quantity ().to (convertible_unit ("%" )).magnitude :g} %). '
1985+ f'and indirect costs (default: '
1986+ f'{ self .indirect_capital_cost_percentage .quantity ().to (convertible_unit ("%" )).magnitude } %) '
1987+ f'are added. '
1988+ 'The built-in cost correlation does not include the cost of pipelines to an off-site heat '
1989+ 'user or a district-heating system. These costs are estimated at $750 per meter pipeline '
1990+ 'length and can be manually added by the user to the pipeline distribution costs.'
19061991 )
19071992 self .Cpiping = self .OutputParameterDict [self .Cpiping .Name ] = OutputParameter (
19081993 Name = "Transmission pipeline costs" ,
@@ -1917,7 +2002,9 @@ def __init__(self, model: Model):
19172002 UnitType = Units .CURRENCYFREQUENCY ,
19182003 PreferredUnits = CurrencyFrequencyUnit .MDOLLARSPERYEAR ,
19192004 CurrentUnits = CurrencyFrequencyUnit .MDOLLARSPERYEAR ,
1920- ToolTipText = 'Assumes $3.5/1,000 gallons of water' # TODO parameterize
2005+ ToolTipText = f'Default correlation: Assumes $3.50/1,000 gallons of water. '
2006+ f'Provide { self .oamwateradjfactor .Name } to multiply the default correlation.'
2007+ # Note: $3.50 could possibly be parameterized, but adjustment factor param serves the same purpose for now.
19212008 )
19222009 self .CCap = self .OutputParameterDict [self .CCap .Name ] = OutputParameter (
19232010 Name = "Total Capital Cost" ,
@@ -1934,7 +2021,9 @@ def __init__(self, model: Model):
19342021 display_name = 'Total operating and maintenance costs' ,
19352022 UnitType = Units .CURRENCYFREQUENCY ,
19362023 PreferredUnits = CurrencyFrequencyUnit .MDOLLARSPERYEAR ,
1937- CurrentUnits = CurrencyFrequencyUnit .MDOLLARSPERYEAR
2024+ CurrentUnits = CurrencyFrequencyUnit .MDOLLARSPERYEAR ,
2025+ ToolTipText = f'GEOPHIRES estimates the annual O&M costs as the sum of the annual surface plant, wellfield, '
2026+ f'make-up water, and pumping O&M costs.'
19382027 )
19392028 self .averageannualpumpingcosts = OutputParameter (
19402029 Name = "Average Annual Pumping Costs" ,
0 commit comments