Skip to content

Commit 12bfa8d

Browse files
Merge branch 'NREL:main' into main
2 parents ecc1444 + ed6e3dd commit 12bfa8d

File tree

3 files changed

+116
-64
lines changed

3 files changed

+116
-64
lines changed

setup.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,10 @@ def read(*names, **kwargs):
7777
'h5py==3.10.0', # TODO resolve apparent h5py==3.11.0 build compatibility issues on some platforms
7878
'scipy',
7979
'iapws',
80-
'coolprop',
80+
'coolprop; python_version > "3.8"',
81+
# coolprop > 6.7.0 fails on Python 3.8, see
82+
# https://github.com/softwareengineerprogrammer/GEOPHIRES/actions/runs/14599234458/job/40952924048?pr=69#step:5:302
83+
'coolprop==6.7.0; python_version == "3.8"',
8184
'rich',
8285
'pylocker',
8386
],

src/geophires_x/SBTReservoir.py

Lines changed: 100 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,18 @@
55
import pandas as pd
66
from scipy.special import erf, erfc, jv, yv, exp1
77
from scipy.interpolate import interp1d
8+
from scipy.integrate import trapezoid
89
import scipy.io as sio
910
import matplotlib.pyplot as plt
1011

12+
import CoolProp.CoolProp as CP
13+
1114
import geophires_x.Model as Model
1215
from .CylindricalReservoir import CylindricalReservoir
1316
from .OptionList import FlowrateModel, InjectionTemperatureModel, Configuration
1417
from .Parameter import intParameter, floatParameter, OutputParameter, ReadParameter, strParameter, boolParameter
1518
from .Reservoir import Reservoir
1619
from .Units import *
17-
import sys
1820
from functools import lru_cache
1921

2022

@@ -378,6 +380,8 @@ def Calculate_Coaxial(self, model):
378380
"""
379381
model.logger.info(f'Init {str(__class__)}: {sys._getframe().f_code.co_name}')
380382

383+
raise NotImplementedError('SBT with coaxial configuration is not implemented at this time.')
384+
381385
# Clear all equivalent: Initialize variables and import necessary libraries
382386

383387
# SBT v2 for co-axial heat exchanger with high-temperature capability
@@ -458,28 +462,30 @@ def Calculate_Coaxial(self, model):
458462
eps_annulus = Dh_annulus * piperoughness # Relative roughness annulus [-]
459463
eps_centerpipe = 2 * radiuscenterpipe * piperoughness # Relative roughness inner pipe [-]
460464

465+
# These variables are set but never used, and sio.loadmat is causing a "No such file" error.
466+
# (see https://github.com/NREL/GEOPHIRES-X/issues/373)
461467
# Variable fluid properties logic
462-
if variablefluidproperties == 0:
463-
Pvector = [1, 1e9]
464-
Tvector = [1, 1e4]
465-
density = np.full((2, 2), rho_f)
466-
heatcapacity = np.full((2, 2), cp_f)
467-
thermalconductivity = np.full((2, 2), k_f)
468-
viscosity = np.full((2, 2), mu_f)
469-
thermalexpansion = np.zeros((2, 2))
470-
else:
471-
print('Loading fluid properties ...')
472-
if fluid == 1:
473-
# Load properties for water from pre-generated CoolProp data
474-
properties = sio.loadmat('properties_H2O_HT_v3.mat')
475-
print('Fluid properties for water loaded successfully')
476-
elif fluid == 2:
477-
# Load properties for CO2 from pre-generated CoolProp data
478-
properties = sio.loadmat('properties_CO2.mat')
479-
print('Fluid properties for CO2 loaded successfully')
480-
else:
481-
print('No valid fluid selected')
482-
exit()
468+
#if variablefluidproperties == 0:
469+
# Pvector = [1, 1e9]
470+
# Tvector = [1, 1e4]
471+
# density = np.full((2, 2), rho_f)
472+
# heatcapacity = np.full((2, 2), cp_f)
473+
# thermalconductivity = np.full((2, 2), k_f)
474+
# viscosity = np.full((2, 2), mu_f)
475+
# thermalexpansion = np.zeros((2, 2))
476+
#else:
477+
# print('Loading fluid properties ...')
478+
# if fluid == 1:
479+
# # Load properties for water from pre-generated CoolProp data
480+
# properties = sio.loadmat('properties_H2O_HT_v3.mat')
481+
# print('Fluid properties for water loaded successfully')
482+
# elif fluid == 2:
483+
# # Load properties for CO2 from pre-generated CoolProp data
484+
# properties = sio.loadmat('properties_CO2.mat')
485+
# print('Fluid properties for CO2 loaded successfully')
486+
# else:
487+
# print('No valid fluid selected')
488+
# exit()
483489

484490
# Length of each segment [m]
485491
Deltaz = np.sqrt(np.diff(x) ** 2 + np.diff(y) ** 2 + np.diff(z) ** 2)
@@ -645,9 +651,10 @@ def Calculate_Coaxial(self, model):
645651
# MIR N = len(x) - 1
646652
N = len(x) - 1
647653
Nboiler = len(boilerelements)
648-
# MIR Nreg = N - Nboiler
649-
Nreg = 1 + N - Nboiler
654+
Nreg = N - Nboiler
655+
#Nreg = 1 + N - Nboiler
650656
self.krock.value_vector = np.full(N, self.krock.value)
657+
k_m_vector = np.zeros(N)
651658
k_m_vector[Nreg:] = k_m_boiler
652659
alpha_m_vector = k_m_vector / self.rhorock.value / self.cprock.value
653660

@@ -662,24 +669,26 @@ def Calculate_Coaxial(self, model):
662669
SoverLSorted = SMatrixSorted / (np.ones((N, 1)) * Deltaz)
663670
mindexNPCP = np.argmax(np.min(SoverLSorted, axis=1) < LimitSoverL)
664671

665-
# MIR midpointsx = 0.5 * x[1:] + 0.5 * x[:-1]
666-
# MIR midpointsy = 0.5 * y[1:] + 0.5 * y[:-1]
667-
# MIR midpointsz = 0.5 * z[1:] + 0.5 * z[:-1]
668-
midpointsx = 0.5 * x + 0.5 * x
669-
midpointsy = 0.5 * y + 0.5 * y
670-
midpointsz = 0.5 * z + 0.5 * z
672+
midpointsx = 0.5 * x[1:] + 0.5 * x[:-1]
673+
midpointsy = 0.5 * y[1:] + 0.5 * y[:-1]
674+
midpointsz = 0.5 * z[1:] + 0.5 * z[:-1]
675+
#midpointsx = 0.5 * x + 0.5 * x
676+
#midpointsy = 0.5 * y + 0.5 * y
677+
#midpointsz = 0.5 * z + 0.5 * z
671678
verticalchange = np.diff(z)
672679
# MIR
673-
verticalchange = np.append(verticalchange, verticalchange[-1])
680+
#verticalchange = np.append(verticalchange, verticalchange[-1])
674681

675682
if initialtemperatureprofile == 0:
676683
BBinitial = Tsurf - GeoGradient * midpointsz
677684
Tfluidupnodes = Tsurf - GeoGradient * z
678685
Tfluiddownnodes = Tsurf - GeoGradient * z
679686
elif initialtemperatureprofile == 1:
680687
BBinitial = np.interp(midpointsz, initialtemperaturedata[:, 0], initialtemperaturedata[:, 1])
681-
Tfluidupnodes = np.interp(z, initialtemperaturedata[:, 0], initialtemperaturedata[:, 1])
682-
Tfluiddownnodes = np.interp(z, initialtemperaturedata[:, 0], initialtemperaturedata[:, 1])
688+
#Tfluidupnodes = np.interp(z, initialtemperaturedata[:, 0], initialtemperaturedata[:, 1])
689+
#Tfluiddownnodes = np.interp(z, initialtemperaturedata[:, 0], initialtemperaturedata[:, 1])
690+
Tfluidupnodes = np.interp(z[:-1], initialtemperaturedata[:, 0], initialtemperaturedata[:, 1])
691+
Tfluiddownnodes = np.interp(z[:-1], initialtemperaturedata[:, 0], initialtemperaturedata[:, 1])
683692

684693
# MIR Tfluiddownmidpoints = 0.5 * Tfluiddownnodes[1:] + 0.5 * Tfluiddownnodes[:-1]
685694
# MIR Tfluidupmidpoints = 0.5 * Tfluidupnodes[1:] + 0.5 * Tfluidupnodes[:-1]
@@ -806,26 +815,38 @@ def Calculate_Coaxial(self, model):
806815
self.Tresoutput.value[0] = Tsurf
807816
Poutput[0] = Pin * 1e5
808817

809-
Tfluidupnodesstore = np.zeros((N + 1, len(times)))
810-
Tfluiddownnodesstore = np.zeros((N + 1, len(times)))
811-
# MIR Tfluidupmidpointsstore = np.zeros((N, len(times)))
812-
Tfluidupmidpointsstore = np.zeros((N + 1, len(times)))
813-
# MIR Tfluiddownmidpointsstore = np.zeros((N, len(times)))
814-
Tfluiddownmidpointsstore = np.zeros((N + 1, len(times)))
815-
Pfluidupnodesstore = np.zeros((N + 1, len(times)))
816-
Pfluiddownnodesstore = np.zeros((N + 1, len(times)))
817-
# MIR Pfluidupmidpointsstore = np.zeros((N, len(times)))
818-
# MIR Pfluiddownmidpointsstore = np.zeros((N, len(times)))
819-
Pfluidupmidpointsstore = np.zeros((N + 1, len(times)))
820-
Pfluiddownmidpointsstore = np.zeros((N + 1, len(times)))
821-
Qfluidupnodesstore = np.zeros((N + 1, len(times)))
822-
Qfluiddownnodesstore = np.zeros((N + 1, len(times)))
823-
Phasefluidupnodesstore = np.zeros((N + 1, len(times)))
824-
Phasefluiddownnodesstore = np.zeros((N + 1, len(times)))
825-
Hfluidupnodesstore = np.zeros((N + 1, len(times)))
826-
Hfluiddownnodesstore = np.zeros((N + 1, len(times)))
818+
#Tfluidupnodesstore = np.zeros((N + 1, len(times)))
819+
#Tfluiddownnodesstore = np.zeros((N + 1, len(times)))
820+
Tfluidupnodesstore = np.zeros((N, len(times)))
821+
Tfluiddownnodesstore = np.zeros((N, len(times)))
822+
Tfluidupmidpointsstore = np.zeros((N, len(times)))
823+
#Tfluidupmidpointsstore = np.zeros((N + 1, len(times)))
824+
Tfluiddownmidpointsstore = np.zeros((N, len(times)))
825+
#Tfluiddownmidpointsstore = np.zeros((N + 1, len(times)))
826+
#Pfluidupnodesstore = np.zeros((N + 1, len(times)))
827+
#Pfluiddownnodesstore = np.zeros((N + 1, len(times)))
828+
Pfluidupnodesstore = np.zeros((N, len(times)))
829+
Pfluiddownnodesstore = np.zeros((N, len(times)))
830+
Pfluidupmidpointsstore = np.zeros((N, len(times)))
831+
Pfluiddownmidpointsstore = np.zeros((N, len(times)))
832+
#Pfluidupmidpointsstore = np.zeros((N + 1, len(times)))
833+
#Pfluiddownmidpointsstore = np.zeros((N + 1, len(times)))
834+
#Qfluidupnodesstore = np.zeros((N + 1, len(times)))
835+
#Qfluiddownnodesstore = np.zeros((N + 1, len(times)))
836+
#Phasefluidupnodesstore = np.zeros((N + 1, len(times)))
837+
#Phasefluiddownnodesstore = np.zeros((N + 1, len(times)))
838+
#Hfluidupnodesstore = np.zeros((N + 1, len(times)))
839+
#Hfluiddownnodesstore = np.zeros((N + 1, len(times)))
840+
Qfluidupnodesstore = np.zeros((N, len(times)))
841+
Qfluiddownnodesstore = np.zeros((N, len(times)))
842+
Phasefluidupnodesstore = np.zeros((N, len(times)))
843+
Phasefluiddownnodesstore = np.zeros((N, len(times)))
844+
Hfluidupnodesstore = np.zeros((N, len(times)))
845+
Hfluiddownnodesstore = np.zeros((N, len(times)))
827846
Qinterexchangestore = np.zeros((N, len(times)))
828847
QinterexchangeUp = np.zeros(N)
848+
velocityfluiddownmidpointsstore = np.zeros((N, len(times)))
849+
heatcapacityfluidupmidpointsstore = np.zeros((N, len(times)))
829850

830851
# Store initial values
831852
Tfluidupnodesstore[:, 0] = Tfluidupnodes
@@ -841,6 +862,8 @@ def Calculate_Coaxial(self, model):
841862
Phasefluidupnodesstore[:, 0] = Phasefluidupnodes
842863
Phasefluiddownnodesstore[:, 0] = Phasefluiddownnodes
843864
Qinterexchangestore[:, 0] = np.zeros(N)
865+
velocityfluiddownmidpointsstore[:, 0] = velocityfluiddownmidpoints
866+
heatcapacityfluidupmidpointsstore[:, 0] = heatcapacityfluidupmidpoints
844867

845868
print('Pre-processing completed successfully. Starting simulation ...')
846869

@@ -937,7 +960,8 @@ def Calculate_Coaxial(self, model):
937960
else:
938961
maxindextoconsider = np.where(maxspacingtest > 1)[0][-1]
939962

940-
if mindexNPCP < maxindextoconsider + 1:
963+
#if mindexNPCP < maxindextoconsider + 1:
964+
if mindexNPCP < maxindextoconsider:
941965
indicestocalculate = SortedIndices[:, mindexNPCP + 1:maxindextoconsider + 1]
942966
NPCP[range(N), indicestocalculate] = Deltaz[indicestocalculate] / (
943967
4 * np.pi * k_m_vector[indicestocalculate] * SMatrix[range(N), indicestocalculate]) * erfc(
@@ -1022,40 +1046,53 @@ def Calculate_Coaxial(self, model):
10221046

10231047
Q[:, i] = BB
10241048

1025-
R[0:N] = Vvector * Tfluiddownmidpointsstore[:, i - 1] / Deltat
1026-
R[0:N] += Q[:, i]
1027-
R[N:2 * N] = Vvector * Tfluidupmidpointsstore[:, i - 1] / Deltat
1028-
R[N:2 * N] += Q[:, i]
1029-
1030-
R[2 * N:3 * N] = Pfluidupmidpointsstore[:, i - 1] - Pfluiddownmidpointsstore[:,
1049+
#R[0:N] = Vvector * Tfluiddownmidpointsstore[:, i - 1] / Deltat
1050+
#R[0:N] += Q[:, i]
1051+
#R[N:2 * N] = Vvector * Tfluidupmidpointsstore[:, i - 1] / Deltat
1052+
#R[N:2 * N] += Q[:, i]
1053+
R[0:N, 0] = Vvector * Tfluiddownmidpointsstore[:, i - 1] / Deltat
1054+
R[0:N, 0] += Q[:, i]
1055+
R[N:2 * N, 0] = Vvector * Tfluidupmidpointsstore[:, i - 1] / Deltat
1056+
R[N:2 * N, 0] += Q[:, i]
1057+
1058+
#R[2 * N:3 * N] = Pfluidupmidpointsstore[:, i - 1] - Pfluiddownmidpointsstore[:,
1059+
# i - 1] + velocityfluiddownmidpointsstore[:,
1060+
# i - 1] * Pfluiddownmidpointsstore[:,
1061+
# i - 1] * Deltat
1062+
R[2 * N:3 * N, 0] = Pfluidupmidpointsstore[:, i - 1] - Pfluiddownmidpointsstore[:,
10311063
i - 1] + velocityfluiddownmidpointsstore[:,
10321064
i - 1] * Pfluiddownmidpointsstore[:,
10331065
i - 1] * Deltat
10341066

1035-
R[3 * N:4 * N] = heatcapacityfluidupmidpointsstore[:, i - 1] * Tfluidupmidpointsstore[:, i - 1]
1067+
#R[3 * N:4 * N] = heatcapacityfluidupmidpointsstore[:, i - 1] * Tfluidupmidpointsstore[:, i - 1]
1068+
R[3 * N:4 * N, 0] = heatcapacityfluidupmidpointsstore[:, i - 1] * Tfluidupmidpointsstore[:, i - 1]
10361069

10371070
try:
10381071
solutions = np.linalg.solve(L, R)
10391072
except np.linalg.LinAlgError:
10401073
print(f'Simulation terminated prematurely due to linear algebra error at time step {i}.')
10411074
break
10421075

1043-
BB = solutions[0:N]
1076+
#BB = solutions[0:N]
1077+
BB = solutions[0:N, 0]
10441078
Tfluidupmidpointsstore[:, i] = BB
10451079
Tfluidupmidpoints = BB
10461080
Tfluidupmidpoints = Tfluidupmidpoints
10471081

1048-
BB = solutions[N:2 * N]
1082+
#BB = solutions[N:2 * N]
1083+
BB = solutions[N:2 * N, 0]
10491084
Tfluiddownmidpointsstore[:, i] = BB
10501085
Tfluiddownmidpoints = BB
10511086
Tfluiddownmidpoints = Tfluiddownmidpoints
10521087

1053-
BB = solutions[2 * N:3 * N]
1088+
#BB = solutions[2 * N:3 * N]
1089+
BB = solutions[2 * N:3 * N, 0]
10541090
Pfluidupmidpointsstore[:, i] = BB
10551091
Pfluidupmidpoints = BB
10561092
Pfluidupmidpoints = Pfluidupmidpoints
10571093

1058-
BB = solutions[3 * N:4 * N]
1094+
#BB = solutions[3 * N:4 * N]
1095+
BB = solutions[3 * N:4 * N, 0]
10591096
Pfluiddownmidpointsstore[:, i] = BB
10601097
Pfluiddownmidpoints = BB
10611098
Pfluiddownmidpoints = Pfluiddownmidpoints

tests/test_geophires_x.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -913,3 +913,15 @@ def test_negative_electricity_production_raises_error(self):
913913
)
914914
client.get_geophires_result(params)
915915
self.assertIn('Electricity production calculated as negative', str(e.exception))
916+
917+
def test_sbt_coaxial_raises_error(self):
918+
client = GeophiresXClient()
919+
with self.assertRaises(RuntimeError) as e:
920+
params = GeophiresInputParameters(
921+
{
922+
'Reservoir Model': 8,
923+
'Well Geometry Configuration': 2,
924+
}
925+
)
926+
client.get_geophires_result(params)
927+
self.assertIn('SBT with coaxial configuration is not implemented', str(e.exception))

0 commit comments

Comments
 (0)