Skip to content

Commit 5b94eb6

Browse files
authored
Merge pull request #467 from NREL/pp/egs_fix
Avoid Geothermal SAM bug that gives CF > 1
2 parents 5873cfd + eb55631 commit 5b94eb6

File tree

3 files changed

+35
-108
lines changed

3 files changed

+35
-108
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ wheels/
2222
*.egg-info/
2323
.installed.cfg
2424
*.egg
25+
.pixi/
2526

2627
# PyInstaller
2728
# Usually these files are written by a python script from a template

reV/SAM/generation.py

+4-63
Original file line numberDiff line numberDiff line change
@@ -1546,23 +1546,6 @@ class Geothermal(AbstractSamGenerationFromWeatherFile):
15461546
- ``conversion_type`` : Integer flag representing the conversion
15471547
plant type. Either Binary (0) or Flash (1). Only values of 0
15481548
or 1 allowed.
1549-
- ``design_temp`` : EGS plant design temperature (in C). Only
1550-
affects EGS runs. This value may be adjusted internally by
1551-
``reV`` under the following conditions:
1552-
1553-
- The design temperature is larger than the resource
1554-
temperature
1555-
- The design temperature is lower than the resource
1556-
temperature by a factor of ``MAX_RT_TO_EGS_RATIO``
1557-
1558-
If either of these conditions are true, the ``design_temp`` is
1559-
adjusted to match the resource temperature input in order to
1560-
avoid SAM errors.
1561-
- ``set_EGS_PDT_to_RT`` : Boolean flag to set EGS design
1562-
temperature to match the resource temperature input. If this
1563-
is ``True``, the ``design_temp`` input is ignored. This helps
1564-
avoid SAM/GETEM errors when the plant design temperature is
1565-
too high/low compared to the resource temperature.
15661549
- ``geotherm.cost.inj_prod_well_ratio`` : Fraction representing
15671550
the injection to production well ratio (0-1). SAM GUI defaults
15681551
to 0.5 for this value, but it is recommended to set this to
@@ -1632,10 +1615,6 @@ class Geothermal(AbstractSamGenerationFromWeatherFile):
16321615
16331616
"""
16341617

1635-
# Per Matt Prilliman on 2/22/24, it's unclear where this ratio originates,
1636-
# but SAM errors out if it's exceeded.
1637-
MAX_RT_TO_EGS_RATIO = 1.134324
1638-
"""Max value of ``resource_temperature``/``EGS_plan_design_temperature``"""
16391618
MODULE = "geothermal"
16401619
PYSAM = PySamGeothermal
16411620
PYSAM_WEATHER_TAG = "file_name"
@@ -1738,52 +1717,14 @@ def _set_resource_temperature(self, resource):
17381717
self.sam_sys_inputs["resource_temp"] = val
17391718

17401719
def _set_egs_plant_design_temperature(self):
1741-
"""Set the EGS plant temp to match resource, if necessary"""
1720+
"""Set the EGS plant temp to match resource (avoids cf > 1)"""
17421721
if self.sam_sys_inputs.get("resource_type") != 1:
17431722
return # Not EGS run
17441723

1745-
set_egs_pdt_to_rt = self.sam_sys_inputs.get("set_EGS_PDT_to_RT", False)
1746-
egs_plant_design_temp = self.sam_sys_inputs.get("design_temp", 0)
17471724
resource_temp = self.sam_sys_inputs["resource_temp"]
1748-
1749-
if set_egs_pdt_to_rt:
1750-
msg = (
1751-
"Setting EGS plant design temperature ({}C) to match "
1752-
"resource temperature ({}C)".format(
1753-
egs_plant_design_temp, resource_temp
1754-
)
1755-
)
1756-
logger.info(msg)
1757-
self.sam_sys_inputs["design_temp"] = resource_temp
1758-
return
1759-
1760-
if egs_plant_design_temp > resource_temp:
1761-
msg = (
1762-
"EGS plant design temperature ({}C) exceeds resource "
1763-
"temperature ({}C). Lowering EGS plant design temperature "
1764-
"to match resource temperature".format(
1765-
egs_plant_design_temp, resource_temp
1766-
)
1767-
)
1768-
logger.warning(msg)
1769-
warn(msg)
1770-
self.sam_sys_inputs["design_temp"] = resource_temp
1771-
return
1772-
1773-
if resource_temp / egs_plant_design_temp > self.MAX_RT_TO_EGS_RATIO:
1774-
msg = (
1775-
"EGS plant design temperature ({}C) is lower than resource "
1776-
"temperature ({}C) by more than a factor of {}. Increasing "
1777-
"EGS plant design temperature to match resource "
1778-
"temperature".format(
1779-
egs_plant_design_temp,
1780-
resource_temp,
1781-
self.MAX_RT_TO_EGS_RATIO,
1782-
)
1783-
)
1784-
logger.warning(msg)
1785-
warn(msg)
1786-
self.sam_sys_inputs["design_temp"] = resource_temp
1725+
logger.debug("Setting EGS plant design temperature to match "
1726+
"resource temperature ({}C)".format(resource_temp))
1727+
self.sam_sys_inputs["design_temp"] = resource_temp
17871728

17881729
def _set_nameplate_to_match_resource_potential(self, resource):
17891730
"""Set the nameplate capacity to match the resource potential."""

tests/test_gen_geothermal.py

+30-45
Original file line numberDiff line numberDiff line change
@@ -414,16 +414,13 @@ def test_gen_egs_too_high_egs_plant_design_temp(sample_resource_data):
414414
assert output not in gen.out
415415

416416

417-
@pytest.mark.parametrize(
418-
"sample_resource_data",
419-
[{"temp": 200 * Geothermal.MAX_RT_TO_EGS_RATIO + 10, "potential": 20}],
420-
indirect=True,
421-
)
417+
@pytest.mark.parametrize("sample_resource_data",
418+
[{"temp": 310, "potential": 20}], indirect=True)
422419
def test_gen_egs_too_low_egs_plant_design_temp(sample_resource_data):
423420
"""Test generation for EGS too low plant design temp"""
424421
points = slice(0, 1)
425422
geo_sam_file, geo_res_file = sample_resource_data
426-
high_temp = 200 * Geothermal.MAX_RT_TO_EGS_RATIO + 10
423+
high_temp = 310
427424

428425
with open(DEFAULT_GEO_SAM_FILE) as fh:
429426
geo_config = json.load(fh)
@@ -434,81 +431,69 @@ def test_gen_egs_too_low_egs_plant_design_temp(sample_resource_data):
434431
with open(geo_sam_file, "w") as fh:
435432
json.dump(geo_config, fh)
436433

437-
output_request = ("design_temp",)
434+
output_request = ("design_temp", "cf_mean")
438435
with pytest.warns(UserWarning):
439-
gen = Gen(
440-
"geothermal",
441-
points,
442-
geo_sam_file,
443-
geo_res_file,
444-
output_request=output_request,
445-
sites_per_worker=1,
446-
scale_outputs=True,
447-
)
436+
gen = Gen("geothermal",
437+
points,
438+
geo_sam_file,
439+
geo_res_file,
440+
output_request=output_request,
441+
sites_per_worker=1,
442+
scale_outputs=True)
448443
gen.run(max_workers=1)
449444

450-
truth_vals = {"design_temp": high_temp}
445+
truth_vals = {"design_temp": high_temp, "cf_mean": 0.995}
451446
for dset in output_request:
452447
truth = truth_vals[dset]
453448
test = gen.out[dset]
454449
if len(test.shape) == 2:
455450
test = np.mean(test, axis=0)
456451

457-
msg = (
458-
"{} outputs do not match baseline value! Values differ "
459-
"at most by: {}".format(dset, np.max(np.abs(truth - test)))
460-
)
452+
msg = ("{} outputs do not match baseline value! Values differ "
453+
"at most by: {}".format(dset, np.max(np.abs(truth - test))))
461454
assert np.allclose(truth, test, rtol=RTOL, atol=ATOL), msg
462455

463456
for output in LCOE_REQUIRED_OUTPUTS:
464457
assert output not in gen.out
465458

466459

467-
@pytest.mark.parametrize(
468-
"sample_resource_data",
469-
[{"temp": 200 * Geothermal.MAX_RT_TO_EGS_RATIO - 1, "potential": 20}],
470-
indirect=True,
471-
)
472-
def test_gen_egs_plant_design_temp_adjusted_from_user(sample_resource_data):
473-
"""Test generation for user-requested match of EGS plant design and RT"""
460+
@pytest.mark.parametrize("sample_resource_data",
461+
[{"temp": 100, "potential": 20}], indirect=True)
462+
def test_gen_egs_too_high_egs_plant_design_temp(sample_resource_data):
463+
"""Test generation for EGS too high plant design temp"""
474464
points = slice(0, 1)
475465
geo_sam_file, geo_res_file = sample_resource_data
476-
not_too_high_temp = 200 * Geothermal.MAX_RT_TO_EGS_RATIO - 1
466+
not_too_high_temp = 100
477467

478468
with open(DEFAULT_GEO_SAM_FILE) as fh:
479469
geo_config = json.load(fh)
480470

481471
geo_config["resource_depth"] = 2000
482472
geo_config["resource_type"] = 1
483473
geo_config["design_temp"] = 200
484-
geo_config["set_EGS_PDT_to_RT"] = True
485474
with open(geo_sam_file, "w") as fh:
486475
json.dump(geo_config, fh)
487476

488-
output_request = ("design_temp",)
477+
output_request = ("design_temp", "cf_mean")
489478
with pytest.warns(UserWarning):
490-
gen = Gen(
491-
"geothermal",
492-
points,
493-
geo_sam_file,
494-
geo_res_file,
495-
output_request=output_request,
496-
sites_per_worker=1,
497-
scale_outputs=True,
498-
)
479+
gen = Gen("geothermal",
480+
points,
481+
geo_sam_file,
482+
geo_res_file,
483+
output_request=output_request,
484+
sites_per_worker=1,
485+
scale_outputs=True)
499486
gen.run(max_workers=1)
500487

501-
truth_vals = {"design_temp": not_too_high_temp}
488+
truth_vals = {"design_temp": not_too_high_temp, "cf_mean": 0.995}
502489
for dset in output_request:
503490
truth = truth_vals[dset]
504491
test = gen.out[dset]
505492
if len(test.shape) == 2:
506493
test = np.mean(test, axis=0)
507494

508-
msg = (
509-
"{} outputs do not match baseline value! Values differ "
510-
"at most by: {}".format(dset, np.max(np.abs(truth - test)))
511-
)
495+
msg = ("{} outputs do not match baseline value! Values differ "
496+
"at most by: {}".format(dset, np.max(np.abs(truth - test))))
512497
assert np.allclose(truth, test, rtol=RTOL, atol=ATOL), msg
513498

514499
for output in LCOE_REQUIRED_OUTPUTS:

0 commit comments

Comments
 (0)