@@ -625,7 +625,8 @@ def __init__(self, model: Model):
625
625
CurrentUnits = CurrencyUnit .MDOLLARS ,
626
626
Provided = False ,
627
627
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.'
629
630
)
630
631
631
632
max_stimulation_cost_per_well_MUSD = 100
@@ -938,7 +939,18 @@ def __init__(self, model: Model):
938
939
UnitType = Units .NONE ,
939
940
Required = True ,
940
941
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).'
942
954
)
943
955
self .FCR = self .ParameterDict [self .FCR .Name ] = floatParameter (
944
956
"Fixed Charge Rate" ,
@@ -1824,22 +1836,28 @@ def __init__(self, model: Model):
1824
1836
f'costs per well. '
1825
1837
f'Provide { self .ccstimadjfactor .Name } to multiply the correlation-calculated cost. '
1826
1838
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.'
1828
1841
)
1829
1842
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 '
1832
1846
f'plus { self .indirect_capital_cost_percentage .quantity ().to (convertible_unit ("%" )).magnitude } % '
1833
1847
f'indirect costs'
1834
1848
)
1849
+ contingency_and_indirect_costs_tooltip = (
1850
+ f'plus { contingency_and_indirect_costs_tooltip_stem } '
1851
+ )
1835
1852
1836
1853
self .Cexpl = self .OutputParameterDict [self .Cexpl .Name ] = OutputParameter (
1837
1854
Name = "Exploration cost" ,
1838
1855
display_name = 'Exploration costs' ,
1839
1856
UnitType = Units .CURRENCY ,
1840
1857
PreferredUnits = CurrencyUnit .MDOLLARS ,
1841
1858
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, '
1843
1861
f'{ contingency_and_indirect_costs_tooltip } . '
1844
1862
f'Provide { self .ccexpladjfactor .Name } to multiply the default correlation. '
1845
1863
f'Provide { self .ccexplfixed .Name } to override the default correlation and set your own cost.'
@@ -1865,14 +1883,21 @@ def __init__(self, model: Model):
1865
1883
ToolTipText = 'Drilling and completion cost per well, including indirect costs '
1866
1884
f'(default: { self .wellfield_indirect_capital_cost_percentage .DefaultValue } %).'
1867
1885
)
1886
+
1887
+ # noinspection SpellCheckingInspection
1868
1888
self .Coamwell = self .OutputParameterDict [self .Coamwell .Name ] = OutputParameter (
1869
1889
Name = "O&M Wellfield cost" ,
1870
1890
display_name = 'Wellfield maintenance costs' ,
1871
1891
UnitType = Units .CURRENCYFREQUENCY ,
1872
1892
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).'
1875
1899
)
1900
+
1876
1901
self .redrilling_annual_cost = self .OutputParameterDict [self .redrilling_annual_cost .Name ] = OutputParameter (
1877
1902
Name = "Redrilling costs" ,
1878
1903
UnitType = Units .CURRENCYFREQUENCY ,
@@ -1884,25 +1909,85 @@ def __init__(self, model: Model):
1884
1909
f'The total is then divided over { model .surfaceplant .plant_lifetime .Name } years to calculate '
1885
1910
f'Redrilling costs per year.'
1886
1911
)
1912
+ # noinspection SpellCheckingInspection
1887
1913
self .Cplant = self .OutputParameterDict [self .Cplant .Name ] = OutputParameter (
1888
1914
Name = "Surface Plant cost" ,
1915
+ display_name = 'Surface power plant costs' ,
1889
1916
UnitType = Units .CURRENCY ,
1890
1917
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.'
1892
1952
)
1893
1953
self .Coamplant = self .OutputParameterDict [self .Coamplant .Name ] = OutputParameter (
1894
1954
Name = "O&M Surface Plant costs" ,
1895
1955
display_name = 'Power plant maintenance costs' ,
1896
1956
UnitType = Units .CURRENCYFREQUENCY ,
1897
1957
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.'
1899
1969
)
1970
+ # noinspection SpellCheckingInspection
1900
1971
self .Cgath = self .OutputParameterDict [self .Cgath .Name ] = OutputParameter (
1901
1972
Name = "Field gathering system cost" ,
1902
1973
display_name = 'Field gathering system costs' ,
1903
1974
UnitType = Units .CURRENCY ,
1904
1975
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.'
1906
1991
)
1907
1992
self .Cpiping = self .OutputParameterDict [self .Cpiping .Name ] = OutputParameter (
1908
1993
Name = "Transmission pipeline costs" ,
@@ -1917,7 +2002,9 @@ def __init__(self, model: Model):
1917
2002
UnitType = Units .CURRENCYFREQUENCY ,
1918
2003
PreferredUnits = CurrencyFrequencyUnit .MDOLLARSPERYEAR ,
1919
2004
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.
1921
2008
)
1922
2009
self .CCap = self .OutputParameterDict [self .CCap .Name ] = OutputParameter (
1923
2010
Name = "Total Capital Cost" ,
@@ -1934,7 +2021,9 @@ def __init__(self, model: Model):
1934
2021
display_name = 'Total operating and maintenance costs' ,
1935
2022
UnitType = Units .CURRENCYFREQUENCY ,
1936
2023
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.'
1938
2027
)
1939
2028
self .averageannualpumpingcosts = OutputParameter (
1940
2029
Name = "Average Annual Pumping Costs" ,
0 commit comments