Skip to content

Commit

Permalink
Merge pull request #467 from NREL/pp/egs_fix
Browse files Browse the repository at this point in the history
Avoid Geothermal SAM bug that gives CF > 1
  • Loading branch information
ppinchuk authored Oct 2, 2024
2 parents 5873cfd + eb55631 commit 5b94eb6
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 108 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ wheels/
*.egg-info/
.installed.cfg
*.egg
.pixi/

# PyInstaller
# Usually these files are written by a python script from a template
Expand Down
67 changes: 4 additions & 63 deletions reV/SAM/generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -1546,23 +1546,6 @@ class Geothermal(AbstractSamGenerationFromWeatherFile):
- ``conversion_type`` : Integer flag representing the conversion
plant type. Either Binary (0) or Flash (1). Only values of 0
or 1 allowed.
- ``design_temp`` : EGS plant design temperature (in C). Only
affects EGS runs. This value may be adjusted internally by
``reV`` under the following conditions:
- The design temperature is larger than the resource
temperature
- The design temperature is lower than the resource
temperature by a factor of ``MAX_RT_TO_EGS_RATIO``
If either of these conditions are true, the ``design_temp`` is
adjusted to match the resource temperature input in order to
avoid SAM errors.
- ``set_EGS_PDT_to_RT`` : Boolean flag to set EGS design
temperature to match the resource temperature input. If this
is ``True``, the ``design_temp`` input is ignored. This helps
avoid SAM/GETEM errors when the plant design temperature is
too high/low compared to the resource temperature.
- ``geotherm.cost.inj_prod_well_ratio`` : Fraction representing
the injection to production well ratio (0-1). SAM GUI defaults
to 0.5 for this value, but it is recommended to set this to
Expand Down Expand Up @@ -1632,10 +1615,6 @@ class Geothermal(AbstractSamGenerationFromWeatherFile):
"""

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

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

set_egs_pdt_to_rt = self.sam_sys_inputs.get("set_EGS_PDT_to_RT", False)
egs_plant_design_temp = self.sam_sys_inputs.get("design_temp", 0)
resource_temp = self.sam_sys_inputs["resource_temp"]

if set_egs_pdt_to_rt:
msg = (
"Setting EGS plant design temperature ({}C) to match "
"resource temperature ({}C)".format(
egs_plant_design_temp, resource_temp
)
)
logger.info(msg)
self.sam_sys_inputs["design_temp"] = resource_temp
return

if egs_plant_design_temp > resource_temp:
msg = (
"EGS plant design temperature ({}C) exceeds resource "
"temperature ({}C). Lowering EGS plant design temperature "
"to match resource temperature".format(
egs_plant_design_temp, resource_temp
)
)
logger.warning(msg)
warn(msg)
self.sam_sys_inputs["design_temp"] = resource_temp
return

if resource_temp / egs_plant_design_temp > self.MAX_RT_TO_EGS_RATIO:
msg = (
"EGS plant design temperature ({}C) is lower than resource "
"temperature ({}C) by more than a factor of {}. Increasing "
"EGS plant design temperature to match resource "
"temperature".format(
egs_plant_design_temp,
resource_temp,
self.MAX_RT_TO_EGS_RATIO,
)
)
logger.warning(msg)
warn(msg)
self.sam_sys_inputs["design_temp"] = resource_temp
logger.debug("Setting EGS plant design temperature to match "
"resource temperature ({}C)".format(resource_temp))
self.sam_sys_inputs["design_temp"] = resource_temp

def _set_nameplate_to_match_resource_potential(self, resource):
"""Set the nameplate capacity to match the resource potential."""
Expand Down
75 changes: 30 additions & 45 deletions tests/test_gen_geothermal.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,16 +414,13 @@ def test_gen_egs_too_high_egs_plant_design_temp(sample_resource_data):
assert output not in gen.out


@pytest.mark.parametrize(
"sample_resource_data",
[{"temp": 200 * Geothermal.MAX_RT_TO_EGS_RATIO + 10, "potential": 20}],
indirect=True,
)
@pytest.mark.parametrize("sample_resource_data",
[{"temp": 310, "potential": 20}], indirect=True)
def test_gen_egs_too_low_egs_plant_design_temp(sample_resource_data):
"""Test generation for EGS too low plant design temp"""
points = slice(0, 1)
geo_sam_file, geo_res_file = sample_resource_data
high_temp = 200 * Geothermal.MAX_RT_TO_EGS_RATIO + 10
high_temp = 310

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

output_request = ("design_temp",)
output_request = ("design_temp", "cf_mean")
with pytest.warns(UserWarning):
gen = Gen(
"geothermal",
points,
geo_sam_file,
geo_res_file,
output_request=output_request,
sites_per_worker=1,
scale_outputs=True,
)
gen = Gen("geothermal",
points,
geo_sam_file,
geo_res_file,
output_request=output_request,
sites_per_worker=1,
scale_outputs=True)
gen.run(max_workers=1)

truth_vals = {"design_temp": high_temp}
truth_vals = {"design_temp": high_temp, "cf_mean": 0.995}
for dset in output_request:
truth = truth_vals[dset]
test = gen.out[dset]
if len(test.shape) == 2:
test = np.mean(test, axis=0)

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

for output in LCOE_REQUIRED_OUTPUTS:
assert output not in gen.out


@pytest.mark.parametrize(
"sample_resource_data",
[{"temp": 200 * Geothermal.MAX_RT_TO_EGS_RATIO - 1, "potential": 20}],
indirect=True,
)
def test_gen_egs_plant_design_temp_adjusted_from_user(sample_resource_data):
"""Test generation for user-requested match of EGS plant design and RT"""
@pytest.mark.parametrize("sample_resource_data",
[{"temp": 100, "potential": 20}], indirect=True)
def test_gen_egs_too_high_egs_plant_design_temp(sample_resource_data):
"""Test generation for EGS too high plant design temp"""
points = slice(0, 1)
geo_sam_file, geo_res_file = sample_resource_data
not_too_high_temp = 200 * Geothermal.MAX_RT_TO_EGS_RATIO - 1
not_too_high_temp = 100

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

geo_config["resource_depth"] = 2000
geo_config["resource_type"] = 1
geo_config["design_temp"] = 200
geo_config["set_EGS_PDT_to_RT"] = True
with open(geo_sam_file, "w") as fh:
json.dump(geo_config, fh)

output_request = ("design_temp",)
output_request = ("design_temp", "cf_mean")
with pytest.warns(UserWarning):
gen = Gen(
"geothermal",
points,
geo_sam_file,
geo_res_file,
output_request=output_request,
sites_per_worker=1,
scale_outputs=True,
)
gen = Gen("geothermal",
points,
geo_sam_file,
geo_res_file,
output_request=output_request,
sites_per_worker=1,
scale_outputs=True)
gen.run(max_workers=1)

truth_vals = {"design_temp": not_too_high_temp}
truth_vals = {"design_temp": not_too_high_temp, "cf_mean": 0.995}
for dset in output_request:
truth = truth_vals[dset]
test = gen.out[dset]
if len(test.shape) == 2:
test = np.mean(test, axis=0)

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

for output in LCOE_REQUIRED_OUTPUTS:
Expand Down

0 comments on commit 5b94eb6

Please sign in to comment.