Skip to content

Commit 82637b9

Browse files
adjust Number of Fractures to 65 due to better stats fit. Calculate stats in sensitivity analysis - WIP: TBD whether to include them in analysis doc
1 parent a5ac39f commit 82637b9

10 files changed

Lines changed: 135 additions & 111 deletions

docs/Fervo_Project_Red.md.jinja

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ The variance analysis (results displayed in legend captions) evaluates the predi
172172
Both models demonstrate high predictive fidelity, tracking steady-state flowing temperatures within 1.5°C of the empirical data.
173173

174174
* **Overall Fit:** GEOPHIRES mathematically achieves a tighter overall fit, yielding a lower Root Mean Square Error (RMSE) and a higher coefficient of determination (R²).
175-
* **Systematic Bias:** The Fervo model exhibits slightly less systemic underestimation, with a cold bias of {{ fervo_bias_degc }}°C compared to the GEOPHIRES cold bias of {{ geophires_bias_degc }}°C.
175+
* **Systematic Bias:** The GEOPHIRES model exhibits slightly less systemic underestimation, with a cold bias of {{ geophires_bias_degc }}°C compared to the Fervo cold bias of {{ fervo_bias_degc }}°C.
176176
* **R² Context:** While the Fervo model yields a relatively low R² ({{ fervo_r2 }}), GEOPHIRES achieves a stronger R² of {{ geophires_r2 }}, indicating it more successfully captures the underlying physical trend of the data (the slight thermal drawdown) rather than simply averaging the noise. However, it is important to note that the absolute R² ceiling for both models is inherently suppressed by the dataset. Because the steady-state temperature profile is essentially a flat plateau, natural sensor variance and minor reservoir oscillations may account for a disproportionately large portion of the total variance, keeping the R² scores modest despite the favorable absolute error (RMSE).
177177

178178
<div id="long-term-forecast-section"></div>
1.84 KB
Loading
-904 Bytes
Loading
449 Bytes
Loading
539 Bytes
Loading
426 Bytes
Loading

src/geophires_docs/generate_fervo_project_red_2026_docs.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,7 @@ def _generate_fracture_sensitivity_graph(
504504
steady_state_start_years: float,
505505
sensitivity_graph_path: Path,
506506
show_excluded_measured_temperatures: bool = False,
507+
calculate_stats: bool = True,
507508
) -> None:
508509
_log.info('Running 8-year fracture sensitivity analysis...')
509510

@@ -542,7 +543,13 @@ def _generate_fracture_sensitivity_graph(
542543
base_input_params: GeophiresInputParameters = get_project_red_input_params_and_result()[0]
543544
base_number_of_fractures = int(_get_input_parameters_dict(base_input_params)[number_of_fractures_param_name])
544545

545-
fracture_counts = [base_number_of_fractures, 57, 60, 66, 69]
546+
fracture_counts = [
547+
base_number_of_fractures,
548+
base_number_of_fractures - 6,
549+
base_number_of_fractures - 3,
550+
base_number_of_fractures + 3,
551+
base_number_of_fractures + 6,
552+
]
546553
client = GeophiresXClient()
547554

548555
colors = {
@@ -556,6 +563,13 @@ def _generate_fracture_sensitivity_graph(
556563
base_number_of_fractures: '-.',
557564
}
558565

566+
if calculate_stats:
567+
_log.info(
568+
f'--- FRACTURE SENSITIVITY STATISTICAL ALIGNMENT (Steady-State > {steady_state_start_years} Years) ---'
569+
)
570+
y_true = df_included['Temperature_C'].values
571+
ss_tot = float(np.sum((y_true - np.mean(y_true)) ** 2))
572+
559573
for frac_count in fracture_counts:
560574
input_params: GeophiresInputParameters = ImmutableGeophiresInputParameters(
561575
from_file_path=base_input_params.as_file_path(),
@@ -574,6 +588,17 @@ def _generate_fracture_sensitivity_graph(
574588
geophires_x = [float(step) / float(time_steps_per_year) for step, _ in enumerate(profile)]
575589
geophires_y = [q.magnitude for q in profile]
576590

591+
if calculate_stats and not df_included.empty:
592+
geo_interp = interp1d(geophires_x, geophires_y, kind='linear', fill_value='extrapolate')
593+
y_geo = geo_interp(df_included['Time_Years'])
594+
595+
rmse_g = float(np.sqrt(((y_true - y_geo) ** 2).mean()))
596+
bias_g = float((y_geo - y_true).mean())
597+
ss_res_g = float(np.sum((y_true - y_geo) ** 2))
598+
r2_g = 1.0 - (ss_res_g / ss_tot) if ss_tot != 0.0 else 0.0
599+
600+
_log.info(f'{frac_count} Fractures: RMSE={rmse_g:.2f}°C, R²={r2_g:.4f}, Bias={bias_g:.2f}°C')
601+
577602
label_prefix = 'GEOPHIRES: ' if frac_count == base_number_of_fractures else ''
578603
label_suffix = ' (Baseline)' if frac_count == base_number_of_fractures else ''
579604

@@ -598,7 +623,6 @@ def _generate_fracture_sensitivity_graph(
598623

599624
def _savefig(version: int | str) -> None:
600625
fig.savefig(
601-
# sensitivity_graph_path,
602626
sensitivity_graph_path.with_name(f'{sensitivity_graph_path.stem}-{version}').with_suffix(
603627
sensitivity_graph_path.suffix
604628
),

tests/examples/Fervo_Project_Red-2026.out

Lines changed: 106 additions & 106 deletions
Large diffs are not rendered by default.

tests/examples/Fervo_Project_Red-2026.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Reservoir Thermal Conductivity, 2.7
1717
Number of Segments, 1
1818
Gradient 1, 76.1
1919

20-
Number of Fractures, 63, -- Fervo estimates between 75 and 100 fractures were created. This value is de-rated in the model to account for the physical reality of imperfect flow distribution and uneven utilization across the entire stimulated rock volume (Norbeck and Latimer, 2023).
20+
Number of Fractures, 65, -- Fervo estimates between 75 and 100 fractures were created. This value is de-rated in the model to account for the physical reality of imperfect flow distribution and uneven utilization across the entire stimulated rock volume (Norbeck and Latimer, 2023).
2121
Fracture Shape, 4, -- Rectangular geometry (Shape 4), representing standard transverse hydraulic fractures along a horizontal wellbore.
2222
Fracture Height, 300 foot, -- Estimated vertical propagation of the stimulated fracture network.
2323
Fracture Width, 365 foot, -- Set to match the distance between the injection and production wellbores, assuming a dipole flow field directly connecting the laterals.

tests/geophires_x_tests/test_fervo_project_red_2026.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,4 @@ def _vuq(v_u: dict[str, Any]) -> PlainQuantity:
4545

4646
avg_production_temp_q = _vuq(r.result['RESERVOIR SIMULATION RESULTS']['Average Production Temperature'])
4747
self.assertGreater(avg_production_temp_q, _q(346, 'degF'))
48-
self.assertLess(avg_production_temp_q, _q(356, 'degF'))
48+
self.assertLess(avg_production_temp_q, _q(357, 'degF'))

0 commit comments

Comments
 (0)