DiadFit 0.0.84__tar.gz → 0.0.88__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {DiadFit-0.0.84 → DiadFit-0.0.88}/PKG-INFO +1 -1
- {DiadFit-0.0.84 → DiadFit-0.0.88}/setup.py +3 -1
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/CO2_EOS.py +2 -2
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/CO2_H2O_EOS.py +173 -90
- DiadFit-0.0.88/src/DiadFit/CO2_in_bubble_error.py +499 -0
- DiadFit-0.0.88/src/DiadFit/Highrho_polyfit_dataUCB_1117_1400.pkl +0 -0
- DiadFit-0.0.88/src/DiadFit/Highrho_polyfit_dataUCB_1117_1447.pkl +0 -0
- DiadFit-0.0.88/src/DiadFit/Highrho_polyfit_dataUCB_1220_1400.pkl +0 -0
- DiadFit-0.0.88/src/DiadFit/Highrho_polyfit_dataUCB_1220_1447.pkl +0 -0
- DiadFit-0.0.88/src/DiadFit/Highrho_polyfit_dataUCB_1220_1567.pkl +0 -0
- DiadFit-0.0.88/src/DiadFit/Highrho_polyfit_data_CMASS_24C.pkl +0 -0
- DiadFit-0.0.88/src/DiadFit/Lowrho_polyfit_dataUCB_1117_1400.pkl +0 -0
- DiadFit-0.0.84/src/DiadFit/Lowrho_polyfit_dataUCB_1117_1400.pkl → DiadFit-0.0.88/src/DiadFit/Lowrho_polyfit_dataUCB_1117_1447.pkl +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/Lowrho_polyfit_dataUCB_1220_1400.pkl +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/Lowrho_polyfit_dataUCB_1220_1447.pkl +0 -0
- DiadFit-0.0.88/src/DiadFit/Lowrho_polyfit_dataUCB_1220_1567.pkl +0 -0
- DiadFit-0.0.88/src/DiadFit/Lowrho_polyfit_data_CMASS_24C.pkl +0 -0
- DiadFit-0.0.88/src/DiadFit/Mediumrho_polyfit_dataUCB_1117_1400.pkl +0 -0
- DiadFit-0.0.88/src/DiadFit/Mediumrho_polyfit_dataUCB_1117_1447.pkl +0 -0
- DiadFit-0.0.88/src/DiadFit/Mediumrho_polyfit_dataUCB_1220_1400.pkl +0 -0
- DiadFit-0.0.88/src/DiadFit/Mediumrho_polyfit_dataUCB_1220_1447.pkl +0 -0
- DiadFit-0.0.88/src/DiadFit/Mediumrho_polyfit_dataUCB_1220_1567.pkl +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/_version.py +1 -1
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/densimeter_fitting.py +7 -1
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/densimeters.py +182 -40
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/density_depth_crustal_profiles.py +37 -5
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/diads.py +85 -48
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/error_propagation.py +141 -229
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/importing_data_files.py +81 -15
- DiadFit-0.0.88/src/DiadFit/lookup_table.csv +64001 -0
- DiadFit-0.0.88/src/DiadFit/lookup_table_noneg.csv +63707 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/ne_lines.py +58 -29
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit.egg-info/PKG-INFO +1 -1
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit.egg-info/SOURCES.txt +10 -0
- DiadFit-0.0.84/src/DiadFit/CO2_in_bubble_error.py +0 -397
- DiadFit-0.0.84/src/DiadFit/Highrho_polyfit_dataUCB_1117_1400.pkl +0 -0
- DiadFit-0.0.84/src/DiadFit/Highrho_polyfit_dataUCB_1220_1400.pkl +0 -0
- DiadFit-0.0.84/src/DiadFit/Highrho_polyfit_dataUCB_1220_1447.pkl +0 -0
- DiadFit-0.0.84/src/DiadFit/Mediumrho_polyfit_dataUCB_1117_1400.pkl +0 -0
- DiadFit-0.0.84/src/DiadFit/Mediumrho_polyfit_dataUCB_1220_1400.pkl +0 -0
- DiadFit-0.0.84/src/DiadFit/Mediumrho_polyfit_dataUCB_1220_1447.pkl +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/README.md +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/setup.cfg +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/H2O_fitting.py +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/Highrho_polyfit_data.pkl +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/Highrho_polyfit_data_CCMR.pkl +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/Highrho_polyfit_data_CMASS.pkl +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/Lowrho_polyfit_data.pkl +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/Lowrho_polyfit_data_CCMR.pkl +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/Lowrho_polyfit_data_CMASS.pkl +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/Mediumrho_polyfit_data.pkl +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/Mediumrho_polyfit_data_CCMR.pkl +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/Mediumrho_polyfit_data_CMASS.pkl +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/Psensor.py +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/__init__.py +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/argon_lines.py +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/cosmicray_filter.py +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/molar_gas_proportions.py +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit/relaxifi.py +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit.egg-info/dependency_links.txt +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit.egg-info/requires.txt +0 -0
- {DiadFit-0.0.84 → DiadFit-0.0.88}/src/DiadFit.egg-info/top_level.txt +0 -0
@@ -829,7 +829,7 @@ def calculate_SP19942(T_K, target_pressure_MPa):
|
|
829
829
|
target_p=np.array(target_pressure_MPa)
|
830
830
|
Density=calculate_Density_Sterner_Pitzer_1994(T_K=T_K, target_pressure_MPa=target_p)
|
831
831
|
else:
|
832
|
-
Density=np.
|
832
|
+
Density=np.zeros(len(target_pressure_MPa))
|
833
833
|
for i in range(0, len(target_pressure_MPa)):
|
834
834
|
Density[i]=calculate_Density_Sterner_Pitzer_1994(T_K=T_K, target_pressure_MPa=target_pressure_MPa[i])
|
835
835
|
return Density
|
@@ -860,7 +860,7 @@ def calculate_SP1994_Temp(CO2_dens_gcm3, target_pressure_MPa):
|
|
860
860
|
target_p=np.array(target_pressure_MPa)
|
861
861
|
Density=calculate_Temp_Sterner_Pitzer_1994(CO2_dens_gcm3=CO2_dens_gcm3, target_pressure_MPa=target_p)
|
862
862
|
else:
|
863
|
-
Density=np.
|
863
|
+
Density=np.zeros(len(target_pressure_MPa))
|
864
864
|
for i in range(0, len(target_pressure_MPa)):
|
865
865
|
Density[i]=calculate_Temp_Sterner_Pitzer_1994(CO2_dens_gcm3=CO2_dens_gcm3, target_pressure_MPa=target_pressure_MPa[i])
|
866
866
|
return Density
|
@@ -102,45 +102,7 @@ aH2[13] = -4.13039220 / 10**1 # alpha for CO2
|
|
102
102
|
aH2[14] = -8.47988634 # beta for CO2
|
103
103
|
aH2[15] = 2.800 / 10**2 # gamma for CO2
|
104
104
|
|
105
|
-
|
106
|
-
# def ensure_series(a, b, c):
|
107
|
-
# # Determine the target length
|
108
|
-
# lengths = [len(a) if isinstance(a, pd.Series) else None,
|
109
|
-
# len(b) if isinstance(b, pd.Series) else None,
|
110
|
-
# len(c) if isinstance(c, pd.Series) else None]
|
111
|
-
# lengths = [l for l in lengths if l is not None]
|
112
|
-
# target_length = max(lengths) if lengths else 1
|
113
|
-
#
|
114
|
-
# # Convert each input to a Series of the target length
|
115
|
-
# if not isinstance(a, pd.Series):
|
116
|
-
# a = pd.Series([a] * target_length)
|
117
|
-
# if not isinstance(b, pd.Series):
|
118
|
-
# b = pd.Series([b] * target_length)
|
119
|
-
# if not isinstance(c, pd.Series):
|
120
|
-
# c = pd.Series([c] * target_length)
|
121
|
-
#
|
122
|
-
# return a, b, c
|
123
|
-
#
|
124
|
-
#
|
125
|
-
# def ensure_series_4(a, b, c, d):
|
126
|
-
# # Determine the target length
|
127
|
-
# lengths = [len(a) if isinstance(a, pd.Series) else None,
|
128
|
-
# len(b) if isinstance(b, pd.Series) else None,
|
129
|
-
# len(c) if isinstance(c, pd.Series) else None,
|
130
|
-
# len(d) if isinstance(d, pd.Series) else None]
|
131
|
-
# lengths = [l for l in lengths if l is not None]
|
132
|
-
# target_length = max(lengths) if lengths else 1
|
133
|
-
#
|
134
|
-
# # Convert each input to a Series of the target length
|
135
|
-
# if not isinstance(a, pd.Series):
|
136
|
-
# a = pd.Series([a] * target_length)
|
137
|
-
# if not isinstance(b, pd.Series):
|
138
|
-
# b = pd.Series([b] * target_length)
|
139
|
-
# if not isinstance(c, pd.Series):
|
140
|
-
# c = pd.Series([c] * target_length)
|
141
|
-
# if not isinstance(d, pd.Series):
|
142
|
-
# d = pd.Series([d] * target_length)
|
143
|
-
# return a, b, c, d
|
105
|
+
|
144
106
|
|
145
107
|
import pandas as pd
|
146
108
|
import numpy as np
|
@@ -257,7 +219,7 @@ def pureEOS_CF(i, V, P, B, C, D, E, F, Vc, TK, b, g):
|
|
257
219
|
|
258
220
|
# Volume iterative function using Netwon-Raphson method.
|
259
221
|
def purevolume(i, V, P, B, C, D, E, F, Vc, TK, b, g):
|
260
|
-
""" Using the pure EOS, this function solves for the best volume using the pureEOS residual calculated above
|
222
|
+
""" Using the pure EOS, this function solves for the best molar volume (in cm3/mol) using the pureEOS residual calculated above
|
261
223
|
|
262
224
|
It returns the volume.
|
263
225
|
|
@@ -280,9 +242,9 @@ def purevolume(i, V, P, B, C, D, E, F, Vc, TK, b, g):
|
|
280
242
|
return V
|
281
243
|
|
282
244
|
def purepressure(i, V, P, TK):
|
283
|
-
""" Using the pure EOS, this function solves for the best pressure using the pureEOS residual calculated above
|
245
|
+
""" Using the pure EOS, this function solves for the best pressure (in bars) using the pureEOS residual calculated above
|
284
246
|
|
285
|
-
It returns the pressure
|
247
|
+
It returns the pressure in bars
|
286
248
|
|
287
249
|
"""
|
288
250
|
for iter in range(1, 51):
|
@@ -294,6 +256,10 @@ def purepressure(i, V, P, TK):
|
|
294
256
|
# Update the pressure using the Newton-Raphson method
|
295
257
|
Pnew = P - pureEOS(i, V, P, B, C, D, E, F, Vc, TK, b, g) / diff
|
296
258
|
|
259
|
+
# Dont allow negative solutions
|
260
|
+
if Pnew < 0:
|
261
|
+
Pnew = 30000
|
262
|
+
|
297
263
|
# Check if the update is within the tolerance (0.000001)
|
298
264
|
if abs(Pnew - P) <= 0.000001:
|
299
265
|
break
|
@@ -308,13 +274,13 @@ def purepressure(i, V, P, TK):
|
|
308
274
|
|
309
275
|
|
310
276
|
def mol_vol_to_density(mol_vol, XH2O):
|
311
|
-
""" Converts molar
|
277
|
+
""" Converts molar volume (cm3/mol) to density (g/cm3) for a given XH2O"""
|
312
278
|
density=((1-XH2O)*44 + (XH2O)*18)/mol_vol
|
313
279
|
return density
|
314
280
|
|
315
281
|
def pure_lnphi(i, Z, B, Vc, V, C, D, E, F, g, b):
|
316
282
|
"""
|
317
|
-
This function calculates the fugacity coefficient from the equation of state for a pure fluid
|
283
|
+
This function calculates the fugacity coefficient (kbar) from the equation of state for a pure fluid
|
318
284
|
|
319
285
|
"""
|
320
286
|
lnph = Z[i] - 1.0 - math.log(Z[i]) + (B[i] * Vc[i] / V[i]) + (C[i] * Vc[i] * Vc[i] / (2.0 * V[i] * V[i]))
|
@@ -358,7 +324,7 @@ def mixEOS_CF(V, P, BVc, CVc2, DVc4, EVc5, FVc2, bmix, gVc2, TK):
|
|
358
324
|
|
359
325
|
|
360
326
|
def mixvolume(V, P, BVc, CVc2, DVc4, EVc5, FVc2, bmix, gVc2, TK):
|
361
|
-
""" This function iterates in volume space to get the best match to the entered pressure using the mixEOS function above.
|
327
|
+
""" This function iterates in volume space to get the best match volume (cm3/mol) to the entered pressure using the mixEOS function above.
|
362
328
|
|
363
329
|
"""
|
364
330
|
for iter in range(1, 51):
|
@@ -371,10 +337,61 @@ def mixvolume(V, P, BVc, CVc2, DVc4, EVc5, FVc2, bmix, gVc2, TK):
|
|
371
337
|
|
372
338
|
return V
|
373
339
|
|
340
|
+
import warnings as w
|
341
|
+
|
342
|
+
## We are going to have to use a look up table to help the netwon raphson converge.
|
343
|
+
|
344
|
+
# Load the lookup table from the CSV file
|
345
|
+
DiadFit_dir=Path(__file__).parent
|
346
|
+
file_str='lookup_table_noneg.csv'
|
347
|
+
dz06_lookuptable=pd.read_csv(DiadFit_dir/file_str)
|
348
|
+
#df = pd.read_csv('lookup_table_noneg.csv')
|
349
|
+
|
350
|
+
|
351
|
+
|
352
|
+
|
353
|
+
|
354
|
+
def get_initial_guess(V_target, T_K_target, XH2O_target):
|
355
|
+
# Calculate the Euclidean distance from the target point to all points in the table
|
356
|
+
# We normalize each dimension by its range to give equal weight to all parameters
|
357
|
+
|
358
|
+
|
359
|
+
df=dz06_lookuptable
|
360
|
+
|
361
|
+
# code to find best value
|
362
|
+
|
363
|
+
P_range = df['P_kbar'].max() - df['P_kbar'].min()
|
364
|
+
T_K_range = df['T_K'].max() - df['T_K'].min()
|
365
|
+
XH2O_range = df['XH2O'].max() - df['XH2O'].min()
|
366
|
+
V_range = df['V'].max() - df['V'].min()
|
367
|
+
|
368
|
+
# Calculate normalized distances
|
369
|
+
distances = np.sqrt(
|
370
|
+
((df['P_kbar'] - df['P_kbar'].mean()) / P_range) ** 2 +
|
371
|
+
((df['T_K'] - T_K_target) / T_K_range) ** 2 +
|
372
|
+
((df['XH2O'] - XH2O_target) / XH2O_range) ** 2 +
|
373
|
+
((df['V'] - V_target) / V_range) ** 2
|
374
|
+
)
|
375
|
+
|
376
|
+
# Find the index of the closest row in the DataFrame
|
377
|
+
closest_index = distances.argmin()
|
378
|
+
|
379
|
+
# Retrieve the P_kbar value from the closest row
|
380
|
+
initial_guess_P = df.iloc[closest_index]['P_kbar']
|
381
|
+
|
382
|
+
|
383
|
+
|
384
|
+
return initial_guess_P
|
385
|
+
|
386
|
+
|
387
|
+
|
388
|
+
|
374
389
|
def mixpressure(P, V, TK, Y):
|
375
|
-
""" This function iterates in pressure space to get the best match to the entered volume using the mixEOS function above.
|
390
|
+
""" This function iterates in pressure space to get the best match in bars to the entered volume in cm3/mol using the mixEOS function above.
|
376
391
|
|
377
392
|
"""
|
393
|
+
|
394
|
+
|
378
395
|
for iter in range(1, 51):
|
379
396
|
k1_temperature, k2_temperature, k3_temperature, a1, a2, g, b, Vc, B, C, D, E, F, Vguess=get_EOS_params(P, TK)
|
380
397
|
Bij, Vcij, BVc_prm, BVc, Cijk, Vcijk, CVc2_prm, CVc2, Dijklm, Vcijklm, DVc4_prm, DVc4, Eijklmn, Vcijklmn, EVc5_prm, EVc5, Fij, FVc2_prm, FVc2, bmix, b_prm, gijk, gVc2_prm, gVc2=mixing_rules(B, C,D, E, F, Vc, Y, b, g, k1_temperature, k2_temperature, k3_temperature)
|
@@ -382,15 +399,63 @@ def mixpressure(P, V, TK, Y):
|
|
382
399
|
diff = ((mixEOS(V, P + 0.0001, BVc, CVc2, DVc4, EVc5, FVc2, bmix, gVc2, TK)
|
383
400
|
- mixEOS(V, P, BVc, CVc2, DVc4, EVc5, FVc2, bmix, gVc2, TK)) / 0.0001)
|
384
401
|
Pnew = P - mixEOS(V, P, BVc, CVc2, DVc4, EVc5, FVc2, bmix, gVc2, TK) / diff
|
402
|
+
|
403
|
+
|
404
|
+
|
405
|
+
|
385
406
|
if abs(Pnew - P) <= 0.000001:
|
386
407
|
break
|
408
|
+
|
387
409
|
P = Pnew
|
388
410
|
|
389
411
|
return P
|
390
412
|
|
413
|
+
# # Dont allow negative solutions
|
414
|
+
# if Pnew<0:
|
415
|
+
# Pnew = 3000
|
416
|
+
|
417
|
+
# if Pnew < 10000 and Pnew>0 and V<50:
|
418
|
+
# w.warn('Sometimes the adapted Newton Raphson method will find a second root at lower (or negative pressure). This initially found a root at P=' + str(np.round(Pnew, 2)) + ', V=' + str(np.round(V)) + '. The algorithm has started its search again at P=3000 bars. Double check your results make sense')
|
419
|
+
#
|
420
|
+
# Pnew = 10000 # Replace 0.0001 with a small positive value that makes sense for your system
|
421
|
+
#
|
422
|
+
|
423
|
+
|
424
|
+
# def mixpressure(P_init, V, TK, Y, max_restarts=3):
|
425
|
+
# """This function iterates in pressure space to get the best match to the entered volume using the mixEOS function above."""
|
426
|
+
#
|
427
|
+
# restarts = 0
|
428
|
+
# while restarts <= max_restarts:
|
429
|
+
# P = P_init
|
430
|
+
# for iter in range(1, 51):
|
431
|
+
# # Your EOS parameters and mixing rules calculations here
|
432
|
+
#
|
433
|
+
# diff = ((mixEOS(V, P + 0.0001, BVc, CVc2, DVc4, EVc5, FVc2, bmix, gVc2, TK) - mixEOS(V, P, BVc, CVc2, DVc4, EVc5, FVc2, bmix, gVc2, TK)) / 0.0001)
|
434
|
+
# Pnew = P - mixEOS(V, P, BVc, CVc2, DVc4, EVc5, FVc2, bmix, gVc2, TK) / diff
|
435
|
+
#
|
436
|
+
# # Don't allow unrealistic solutions but provide a chance to reset
|
437
|
+
# if Pnew < 5000 and V > 10:
|
438
|
+
# warnings.warn('Root forced above 5000 bars due to conditions, attempting restart...')
|
439
|
+
# Pnew = 5000 # Force the pressure up due to your condition
|
440
|
+
# break # Break out of the current iteration loop to allow for a restart
|
441
|
+
#
|
442
|
+
# if abs(Pnew - P) <= 0.000001: # Convergence criterion
|
443
|
+
# return Pnew # Return the converged value
|
444
|
+
# P = Pnew
|
445
|
+
#
|
446
|
+
# restarts += 1 # Increment the number of restarts attempted
|
447
|
+
# P_init = 5000 # Set a new starting point that might be closer to the suspected real root
|
448
|
+
#
|
449
|
+
# warnings.warn('Max restarts reached, solution may not be optimal.')
|
450
|
+
# return P # Return the last computed pressure if all restart attempts fail
|
451
|
+
|
452
|
+
|
453
|
+
|
454
|
+
|
391
455
|
|
392
456
|
|
393
457
|
def mix_lnphi(i, Zmix, BVc_prm, CVc2_prm, DVc4_prm, EVc5_prm, FVc2_prm, FVc2, bmix, b_prm, gVc2, gVc2_prm, Vmix):
|
458
|
+
""" This function calculates lnphi values"""
|
394
459
|
lnph=0
|
395
460
|
|
396
461
|
lnph = -math.log(Zmix)
|
@@ -562,6 +627,8 @@ def mix_fugacity_ind(*, P_kbar, T_K, XH2O, Vmix):
|
|
562
627
|
|
563
628
|
|
564
629
|
def mixing_rules(B, C, D, E, F, Vc, Y, b, g, k1_temperature, k2_temperature, k3_temperature):
|
630
|
+
""" This function applies the DZ06 mixing rules"""
|
631
|
+
|
565
632
|
Bij = np.zeros((2, 2))
|
566
633
|
Vcij = np.zeros((2, 2))
|
567
634
|
BVc_prm = np.zeros(2)
|
@@ -739,7 +806,7 @@ def mixing_rules(B, C, D, E, F, Vc, Y, b, g, k1_temperature, k2_temperature, k3_
|
|
739
806
|
## Getting EOS contsants themselves
|
740
807
|
|
741
808
|
def get_EOS_params(P, TK):
|
742
|
-
""" This function returns the EOS 'constants' if you know the pressure and temperature
|
809
|
+
""" This function returns the EOS 'constants' if you know the pressure (in bars) and temperature (in Kelvin)
|
743
810
|
|
744
811
|
"""
|
745
812
|
|
@@ -813,7 +880,7 @@ def get_EOS_params(P, TK):
|
|
813
880
|
## Lets wrap all these functions up.
|
814
881
|
|
815
882
|
def calculate_molar_volume_ind_DZ2006(*, P_kbar, T_K, XH2O):
|
816
|
-
""" This function calculates molar volume for a known pressure, T in K and XH2O (mol frac) for a single value
|
883
|
+
""" This function calculates molar volume (cm3/mol) for a known pressure (kbar), T in K and XH2O (mol frac) for a single value
|
817
884
|
"""
|
818
885
|
|
819
886
|
P=P_kbar*1000
|
@@ -838,11 +905,14 @@ def calculate_molar_volume_ind_DZ2006(*, P_kbar, T_K, XH2O):
|
|
838
905
|
|
839
906
|
mol_vol=mixvolume(Vguess, P, BVc, CVc2, DVc4, EVc5, FVc2, bmix, gVc2, T_K)
|
840
907
|
|
908
|
+
if mol_vol<0:
|
909
|
+
mol_vol=np.nan
|
910
|
+
|
841
911
|
return mol_vol
|
842
912
|
|
843
913
|
|
844
914
|
def calculate_molar_volume_DZ2006(*, P_kbar, T_K, XH2O):
|
845
|
-
""" Used to calculate molar volume in a loop for multiple inputs
|
915
|
+
""" Used to calculate molar volume (cm3/mol) in a loop for multiple inputs
|
846
916
|
|
847
917
|
|
848
918
|
"""
|
@@ -855,7 +925,7 @@ def calculate_molar_volume_DZ2006(*, P_kbar, T_K, XH2O):
|
|
855
925
|
raise ValueError("All input Pandas Series must have the same length.")
|
856
926
|
|
857
927
|
# Set up loop
|
858
|
-
mol_vol=np.
|
928
|
+
mol_vol=np.zeros(len(P_kbar), float)
|
859
929
|
|
860
930
|
for i in range(0, len(P_kbar)):
|
861
931
|
mol_vol[i]=calculate_molar_volume_ind_DZ2006(P_kbar=P_kbar.iloc[i].astype(float), T_K=T_K.iloc[i].astype(float), XH2O=XH2O.iloc[i].astype(float))
|
@@ -867,40 +937,50 @@ def calculate_molar_volume_DZ2006(*, P_kbar, T_K, XH2O):
|
|
867
937
|
return mol_vol
|
868
938
|
|
869
939
|
def calculate_Pressure_ind_DZ2006(*, mol_vol, T_K, XH2O, Pguess=None):
|
870
|
-
""" This function calculates pressure for a known molar volume, T in K and XH2O (mol frac) for a single value
|
940
|
+
""" This function calculates pressure (in bars) for a known molar volume, T in K and XH2O (mol frac) for a single value. It uses a look up table to get pressure, then a newton and raphson method (implemented in the function mixpressure) to find the best fit pressure. There are some densities, T_K and XH2O values where the volume is negative.
|
871
941
|
"""
|
872
942
|
V=mol_vol
|
873
|
-
if Pguess is None:
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
943
|
+
# if Pguess is None:
|
944
|
+
# if V>1000:
|
945
|
+
# Pguess=1000
|
946
|
+
# elif V<10:
|
947
|
+
# Pguess=20000
|
948
|
+
# else:
|
949
|
+
# Pguess=200
|
950
|
+
|
951
|
+
# Lets get P guess from a look up table
|
952
|
+
# uses a look up table
|
953
|
+
Pguess=get_initial_guess(V_target=V, T_K_target=T_K, XH2O_target=XH2O)*1000
|
954
|
+
|
955
|
+
if Pguess <= 0:
|
956
|
+
return np.nan
|
957
|
+
|
880
958
|
|
881
959
|
TK=T_K
|
882
960
|
|
883
961
|
# lets do for low pressure initially
|
884
962
|
|
885
963
|
|
886
|
-
if XH2O==0:
|
887
|
-
|
964
|
+
# if XH2O==0:
|
965
|
+
# P=purepressure(1, V, Pguess, TK)
|
966
|
+
#
|
967
|
+
# elif XH2O==1:
|
968
|
+
# P=purepressure(0, V, Pguess, TK)
|
969
|
+
#
|
970
|
+
# else:
|
971
|
+
XCO2=1-XH2O
|
972
|
+
Y = [0] * 2
|
973
|
+
Y[0]=XH2O
|
974
|
+
Y[1]=XCO2
|
888
975
|
|
889
|
-
|
890
|
-
P=purepressure(0, V, Pguess, TK)
|
976
|
+
# Now iteratively solve for pressure starting from this initial guess.
|
891
977
|
|
892
|
-
|
893
|
-
XCO2=1-XH2O
|
894
|
-
Y = [0] * 2
|
895
|
-
Y[0]=XH2O
|
896
|
-
Y[1]=XCO2
|
897
|
-
|
898
|
-
P=mixpressure(Pguess, V, T_K, Y)
|
978
|
+
P=mixpressure(Pguess, V, T_K, Y)
|
899
979
|
|
900
980
|
return P
|
901
981
|
|
902
982
|
def calculate_Pressure_DZ2006(*, mol_vol=None, density=None, T_K, XH2O):
|
903
|
-
""" Used to calculate
|
983
|
+
""" Used to calculate pressure in a loop for multiple inputs. Dens - bulk density.
|
904
984
|
|
905
985
|
|
906
986
|
"""
|
@@ -919,7 +999,7 @@ def calculate_Pressure_DZ2006(*, mol_vol=None, density=None, T_K, XH2O):
|
|
919
999
|
raise ValueError("All input Pandas Series must have the same length.")
|
920
1000
|
|
921
1001
|
# Set up loop
|
922
|
-
P=np.
|
1002
|
+
P=np.zeros(len(mol_vol), float)
|
923
1003
|
|
924
1004
|
for i in range(0, len(mol_vol)):
|
925
1005
|
P[i]=calculate_Pressure_ind_DZ2006(mol_vol=mol_vol.iloc[i].astype(float), T_K=T_K.iloc[i].astype(float), XH2O=XH2O.iloc[i].astype(float))
|
@@ -945,12 +1025,12 @@ def mix_fugacity(*, P_kbar, T_K, XH2O, Vmix):
|
|
945
1025
|
if len(set(lengths)) != 1:
|
946
1026
|
raise ValueError("All input Pandas Series must have the same length.")
|
947
1027
|
|
948
|
-
f=np.
|
949
|
-
a_CO2=np.
|
950
|
-
a_H2O=np.
|
951
|
-
f_CO2=np.
|
952
|
-
f_H2O=np.
|
953
|
-
Zmix=np.
|
1028
|
+
f=np.zeros(len(P_kbar), float)
|
1029
|
+
a_CO2=np.zeros(len(P_kbar), float)
|
1030
|
+
a_H2O=np.zeros(len(P_kbar), float)
|
1031
|
+
f_CO2=np.zeros(len(P_kbar), float)
|
1032
|
+
f_H2O=np.zeros(len(P_kbar), float)
|
1033
|
+
Zmix=np.zeros(len(P_kbar), float)
|
954
1034
|
for i in range(0, len(P_kbar)):
|
955
1035
|
|
956
1036
|
f_H2O[i], f_CO2[i], a_H2O[i], a_CO2[i], Zmix[i]=mix_fugacity_ind(P_kbar=P_kbar.iloc[i].astype(float), T_K=T_K.iloc[i].astype(float), XH2O=XH2O.iloc[i].astype(float), Vmix=Vmix.iloc[i].astype(float))
|
@@ -1059,7 +1139,7 @@ def calculate_entrapment_P_XH2O(*, XH2O, CO2_dens_gcm3, T_K, T_K_ambient=37+273.
|
|
1059
1139
|
P_kbar_mixCO2_DZ06_Hloss: Pressure calculated from the reconstructed mixed fluid density using the mixed EOS from Duan and Zhang (2006) assuming H loss
|
1060
1140
|
P_kbar_mixCO2_DZ06_noHloss: Pressure calculated from the reconstructed mixed fluid density using the mixed EOS from Duan and Zhang (2006) assuming H loss
|
1061
1141
|
P Mix_Hloss/P Pure DZ06: Correction factor - e.g. how much deeper the pressure is from the mixed EOS with H loss
|
1062
|
-
P Mix_noHloss/P Pure DZ06: Correction factor - e.g. how much deeper the pressure is from the mixed EOS
|
1142
|
+
P Mix_noHloss/P Pure DZ06: Correction factor - e.g. how much deeper the pressure is from the mixed EOS (assuming no H loss)
|
1063
1143
|
rho_mix_calc_noHloss: Bulk density calculated (C+H)
|
1064
1144
|
rho_mix_calc_Hloss: Bulk density calculated (C+H) after h loss
|
1065
1145
|
CO2_dens_gcm3: Input CO2 density
|
@@ -1079,26 +1159,28 @@ def calculate_entrapment_P_XH2O(*, XH2O, CO2_dens_gcm3, T_K, T_K_ambient=37+273.
|
|
1079
1159
|
# IF water isnt lost
|
1080
1160
|
|
1081
1161
|
# Calculate mass ratio from molar ratio
|
1082
|
-
|
1083
|
-
# Calculate pressure in CO2 fluid
|
1084
|
-
|
1162
|
+
XH2O_mass=(XH2O*18)/((1-XH2O)*44 +(XH2O*18) )
|
1163
|
+
# Calculate pressure in CO2 fluid - returns answer in kbar
|
1164
|
+
P_CO2=calculate_P_for_rho_T_SW96(CO2_dens_gcm3, T_K_ambient)['P_kbar']
|
1085
1165
|
# Now calculate density of H2O fluid
|
1086
1166
|
|
1087
|
-
#
|
1088
|
-
|
1167
|
+
# See https://www.youtube.com/watch?v=6wE4Tk6OjGY
|
1168
|
+
Ptotal=P_CO2/(1-XH2O) # Calculate the total pressure from the pressure we know for CO2.
|
1169
|
+
P_H2O=Ptotal*XH2O # Now calculate the pressure of H2O. You could also do this as PTot*XH2O
|
1170
|
+
|
1171
|
+
# calculate density of H2O using EOS
|
1172
|
+
H2O_dens=calculate_rho_for_P_T_H2O(P_kbar=P_H2O,T_K=T_K_ambient)
|
1089
1173
|
|
1174
|
+
# Calculate the bulk density by re-arranging the two volume equations
|
1175
|
+
rho_orig_no_H_loss=(CO2_dens_gcm3*H2O_dens)/((1-XH2O_mass)*H2O_dens+XH2O_mass*CO2_dens_gcm3)
|
1090
1176
|
|
1091
1177
|
|
1092
|
-
# Assume a system of unit 1. Calculate volume of CO2
|
1093
|
-
VolCO2=(1-mass_ratio)/CO2_dens_gcm3
|
1094
|
-
VolH2O=mass_ratio/rho_H2O
|
1095
|
-
rho_orig_no_H_loss=1/(VolH2O+VolCO2)
|
1096
1178
|
|
1097
1179
|
if fast_calcs is True:
|
1098
1180
|
if Hloss is True:
|
1099
1181
|
P=calculate_Pressure_DZ2006(density=rho_orig_H_loss, T_K=T_K, XH2O=XH2O)
|
1100
1182
|
if Hloss is False:
|
1101
|
-
P=calculate_Pressure_DZ2006(density=
|
1183
|
+
P=calculate_Pressure_DZ2006(density=rho_orig_no_H_loss, T_K=T_K, XH2O=XH2O)
|
1102
1184
|
return P/1000
|
1103
1185
|
|
1104
1186
|
else:
|
@@ -1106,9 +1188,10 @@ def calculate_entrapment_P_XH2O(*, XH2O, CO2_dens_gcm3, T_K, T_K_ambient=37+273.
|
|
1106
1188
|
# Lets calculate the pressure using SW96
|
1107
1189
|
P_SW=calculate_P_for_rho_T(T_K=T_K, CO2_dens_gcm3=rho_meas, EOS='SW96')
|
1108
1190
|
P_SP=calculate_P_for_rho_T(T_K=T_K, CO2_dens_gcm3=rho_meas, EOS='SP94')
|
1109
|
-
#
|
1191
|
+
# Run Duan and Zhang with no XHO@ to start with
|
1110
1192
|
P_DZ=calculate_Pressure_DZ2006(density=rho_meas, T_K=T_K, XH2O=XH2O*0)
|
1111
|
-
# Now doing it with XH2O
|
1193
|
+
# Now doing it with XH2O for two different densities
|
1194
|
+
|
1112
1195
|
P_DZ_mix_H_loss=calculate_Pressure_DZ2006(density=rho_orig_H_loss, T_K=T_K, XH2O=XH2O)
|
1113
1196
|
P_DZ_mix_noH_loss=calculate_Pressure_DZ2006(density=rho_orig_no_H_loss, T_K=T_K, XH2O=XH2O)
|
1114
1197
|
|