PetThermoTools 0.2.32__py3-none-any.whl → 0.2.34__py3-none-any.whl
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.
- PetThermoTools/Barom.py +352 -404
- PetThermoTools/MELTS.py +64 -22
- PetThermoTools/Plotting.py +19 -7
- PetThermoTools/_version.py +1 -1
- PetThermoTools-0.2.34.dist-info/LICENSE.txt +16 -0
- {PetThermoTools-0.2.32.dist-info → PetThermoTools-0.2.34.dist-info}/METADATA +1 -1
- {PetThermoTools-0.2.32.dist-info → PetThermoTools-0.2.34.dist-info}/RECORD +9 -8
- {PetThermoTools-0.2.32.dist-info → PetThermoTools-0.2.34.dist-info}/WHEEL +0 -0
- {PetThermoTools-0.2.32.dist-info → PetThermoTools-0.2.34.dist-info}/top_level.txt +0 -0
PetThermoTools/Barom.py
CHANGED
@@ -10,6 +10,7 @@ from PetThermoTools.GenFuncs import *
|
|
10
10
|
from PetThermoTools.Plotting import *
|
11
11
|
from PetThermoTools.Liq import *
|
12
12
|
from PetThermoTools.MELTS import *
|
13
|
+
from PetThermoTools.Path import *
|
13
14
|
# try:
|
14
15
|
# from PetThermoTools.Holland import *
|
15
16
|
# except:
|
@@ -23,7 +24,357 @@ from tqdm.notebook import tqdm, trange
|
|
23
24
|
from scipy import interpolate
|
24
25
|
from shapely.geometry import MultiPoint, Point, Polygon
|
25
26
|
|
26
|
-
|
27
|
+
from functools import partial
|
28
|
+
import concurrent.futures
|
29
|
+
|
30
|
+
import numpy as np
|
31
|
+
import pandas as pd
|
32
|
+
from joblib import Parallel, delayed
|
33
|
+
import multiprocessing
|
34
|
+
import time
|
35
|
+
|
36
|
+
def path_4_saturation(q, index, *, Model = None, P_bar = None, comp = None, T_maxdrop_C = None, dt_C = None, T_initial_C = None, fO2_buffer = None,
|
37
|
+
fO2_offset = 0.0, H2O_Sat = None, phases = None):
|
38
|
+
if "MELTS" in Model:
|
39
|
+
Results = path_MELTS(P_bar = P_bar,
|
40
|
+
Model=Model,
|
41
|
+
comp=comp,
|
42
|
+
T_maxdrop_C=T_maxdrop_C,
|
43
|
+
dt_C=dt_C,
|
44
|
+
T_initial_C=T_initial_C,
|
45
|
+
find_liquidus=True,
|
46
|
+
fO2_buffer=fO2_buffer,
|
47
|
+
fO2_offset=fO2_offset,
|
48
|
+
fluid_sat=H2O_Sat,
|
49
|
+
Suppress=['rutile', 'tridymite'],
|
50
|
+
phases=phases
|
51
|
+
)
|
52
|
+
q.put([index, Results])
|
53
|
+
return
|
54
|
+
|
55
|
+
def path_4_saturation_multi(q, index, *, Model = None, P_bar = None, comp = None, T_maxdrop_C = None, dt_C = None, T_initial_C = None, fO2_buffer = None,
|
56
|
+
fO2_offset = 0.0, H2O_Sat = None, phases = None):
|
57
|
+
results = {}
|
58
|
+
idx = []
|
59
|
+
|
60
|
+
if "MELTS" in Model:
|
61
|
+
from meltsdynamic import MELTSdynamic
|
62
|
+
|
63
|
+
if Model is None or Model == "MELTSv1.0.2":
|
64
|
+
melts = MELTSdynamic(1)
|
65
|
+
elif Model == "pMELTS":
|
66
|
+
melts = MELTSdynamic(2)
|
67
|
+
elif Model == "MELTSv1.1.0":
|
68
|
+
melts = MELTSdynamic(3)
|
69
|
+
elif Model == "MELTSv1.2.0":
|
70
|
+
melts = MELTSdynamic(4)
|
71
|
+
else:
|
72
|
+
from juliacall import Main as jl, convert as jlconvert
|
73
|
+
|
74
|
+
jl.seval("using MAGEMinCalc")
|
75
|
+
|
76
|
+
comp_julia = jl.seval("Dict")(comp)
|
77
|
+
|
78
|
+
for i in index:
|
79
|
+
# try:
|
80
|
+
if "MELTS" in Model:
|
81
|
+
Results, tr = path_MELTS(P_bar = P_bar[i],
|
82
|
+
Model=Model,
|
83
|
+
comp=comp,
|
84
|
+
T_maxdrop_C=T_maxdrop_C,
|
85
|
+
dt_C=dt_C,
|
86
|
+
T_initial_C=T_initial_C,
|
87
|
+
find_liquidus=True,
|
88
|
+
fO2_buffer=fO2_buffer,
|
89
|
+
fO2_offset=fO2_offset,
|
90
|
+
fluid_sat=H2O_Sat,
|
91
|
+
Suppress=['rutile', 'tridymite'],
|
92
|
+
phases=phases,
|
93
|
+
trail = True,
|
94
|
+
melts = melts
|
95
|
+
)
|
96
|
+
else:
|
97
|
+
if fO2_offset is None:
|
98
|
+
fO2_offset = 0.0
|
99
|
+
|
100
|
+
Results_df = jl.MAGEMinCalc.path(
|
101
|
+
comp=comp_julia, dt_C=dt_C,
|
102
|
+
P_bar=P_bar[i], T_min_C = T_maxdrop_C,
|
103
|
+
Model=Model, fo2_buffer=fO2_buffer,
|
104
|
+
fo2_offset=fO2_offset, find_liquidus=True,
|
105
|
+
frac_xtal = False
|
106
|
+
)
|
107
|
+
|
108
|
+
Results = dict(Results_df)
|
109
|
+
|
110
|
+
tr = True
|
111
|
+
|
112
|
+
idx.append(i)
|
113
|
+
|
114
|
+
|
115
|
+
results[f"index = {i}"] = Results
|
116
|
+
|
117
|
+
if tr is False:
|
118
|
+
break
|
119
|
+
# except:
|
120
|
+
# idx.append(i)
|
121
|
+
|
122
|
+
q.put([idx, results])
|
123
|
+
return
|
124
|
+
|
125
|
+
def mineral_cosaturation(Model="MELTSv1.0.2", cores=int(np.floor(multiprocessing.cpu_count())), bulk=None,
|
126
|
+
phases=['quartz1', 'alkali-feldspar1', 'plagioclase1'],
|
127
|
+
P_bar=np.linspace(250, 5000, 32), Fe3Fet_init=None, H2O_init=None,
|
128
|
+
CO2_init=None, H2O_Sat=False, T_initial_C=None, dt_C=2,
|
129
|
+
T_maxdrop_C=50, T_cut_C=20, find_range=True,
|
130
|
+
find_min=True, fO2_buffer=None, fO2_offset=0.0, timeout = 30):
|
131
|
+
|
132
|
+
comp = bulk.copy()
|
133
|
+
if H2O_Sat:
|
134
|
+
comp['H2O_Liq'] = 20
|
135
|
+
|
136
|
+
comp = comp_fix(Model=Model, comp=comp, Fe3Fet_Liq=Fe3Fet_init,
|
137
|
+
H2O_Liq=H2O_init, CO2_Liq=CO2_init)
|
138
|
+
|
139
|
+
index_in = np.arange(len(P_bar))
|
140
|
+
# index_in = index
|
141
|
+
combined_results = {}
|
142
|
+
index_out = np.array([], dtype=int)
|
143
|
+
|
144
|
+
while len(index_out) < len(index_in):
|
145
|
+
index = np.setdiff1d(index_in, index_out)
|
146
|
+
groups = np.array_split(index, cores)
|
147
|
+
|
148
|
+
processes = []
|
149
|
+
for i in range(len(groups)):
|
150
|
+
q = Queue()
|
151
|
+
p = Process(target = path_4_saturation_multi, args = (q, groups[i]),
|
152
|
+
kwargs = {'Model': Model, 'comp': comp,
|
153
|
+
'T_initial_C': T_initial_C, 'T_maxdrop_C': T_maxdrop_C,
|
154
|
+
'dt_C': dt_C, 'P_bar': P_bar, 'phases': phases,
|
155
|
+
'fO2_buffer': fO2_buffer, 'fO2_offset': fO2_offset})
|
156
|
+
|
157
|
+
processes.append((p, q))
|
158
|
+
p.start()
|
159
|
+
|
160
|
+
for p, q in processes:
|
161
|
+
res = q.get(timeout=timeout)
|
162
|
+
p.join(timeout = 2)
|
163
|
+
p.terminate()
|
164
|
+
|
165
|
+
idx_chunks, results = res
|
166
|
+
|
167
|
+
index_out = np.hstack((index_out, idx_chunks))
|
168
|
+
combined_results.update(results)
|
169
|
+
|
170
|
+
results = combined_results
|
171
|
+
# results = {}
|
172
|
+
# if len(P_bar) > 1:
|
173
|
+
# A = len(P_bar)//cores
|
174
|
+
# B = len(P_bar) % cores
|
175
|
+
|
176
|
+
# if A > 0:
|
177
|
+
# Group = np.zeros(A) + cores
|
178
|
+
# if B > 0:
|
179
|
+
# Group = np.append(Group, B)
|
180
|
+
# else:
|
181
|
+
# Group = np.array([B])
|
182
|
+
|
183
|
+
# # initialise queue
|
184
|
+
# qs = []
|
185
|
+
# q = Queue()
|
186
|
+
|
187
|
+
|
188
|
+
# # run calculations
|
189
|
+
# for k in range(len(Group)):
|
190
|
+
# ps = []
|
191
|
+
|
192
|
+
# for kk in range(int(cores*k), int(cores*k + Group[k])):
|
193
|
+
# p = Process(target = path_4_saturation, args = (q, kk),
|
194
|
+
# kwargs = {'Model': Model, 'comp': comp,
|
195
|
+
# 'T_initial_C': T_initial_C, 'T_maxdrop_C': T_maxdrop_C,
|
196
|
+
# 'dt_C': dt_C, 'P_bar': P_bar[kk], 'phases': phases,
|
197
|
+
# 'fO2_buffer': fO2_buffer, 'fO2_offset': fO2_offset})
|
198
|
+
|
199
|
+
# ps.append(p)
|
200
|
+
# p.start()
|
201
|
+
|
202
|
+
# start = time.time()
|
203
|
+
# for p in ps:
|
204
|
+
# if time.time() - start < timeout - 10:
|
205
|
+
# try:
|
206
|
+
# ret = q.get(timeout = timeout - (time.time()-start) + 10)
|
207
|
+
# except:
|
208
|
+
# ret = []
|
209
|
+
# else:
|
210
|
+
# try:
|
211
|
+
# ret = q.get(timeout = 10)
|
212
|
+
# except:
|
213
|
+
# ret = []
|
214
|
+
|
215
|
+
# qs.append(ret)
|
216
|
+
|
217
|
+
# TIMEOUT = 5
|
218
|
+
# start = time.time()
|
219
|
+
# for p in ps:
|
220
|
+
# if p.is_alive():
|
221
|
+
# while time.time() - start <= TIMEOUT:
|
222
|
+
# if not p.is_alive():
|
223
|
+
# p.join()
|
224
|
+
# p.terminate()
|
225
|
+
# break
|
226
|
+
# time.sleep(.1)
|
227
|
+
# else:
|
228
|
+
# p.terminate()
|
229
|
+
# p.join(5)
|
230
|
+
# else:
|
231
|
+
# p.join()
|
232
|
+
# p.terminate()
|
233
|
+
|
234
|
+
# for kk in range(len(qs)):
|
235
|
+
# if len(qs[kk]) > 0:
|
236
|
+
# index, res = qs[kk]
|
237
|
+
# results[f"P = {P_bar[index]:.2f} bars"] = res.copy()
|
238
|
+
|
239
|
+
Results = stich(Res=results, multi=True, Model=Model)
|
240
|
+
|
241
|
+
## determine the offset between the phases
|
242
|
+
if len(phases) == 3:
|
243
|
+
arr = np.zeros((len(Results.keys()), 4))
|
244
|
+
arr2 = np.zeros((len(Results.keys()), 4))
|
245
|
+
columns = ['P_bar'] + phases + [phases[0] + ' - ' + phases[1], phases[0] + ' - ' + phases[2], phases[1] + ' - ' + phases[2], '3 Phase Saturation']
|
246
|
+
for i, r in enumerate(Results.keys()):
|
247
|
+
for idx, p in enumerate(phases):
|
248
|
+
if p in Results[r]['Mass'].keys():
|
249
|
+
arr[i, idx+1] = Results[r]['Conditions'].loc[Results[r]['Mass'][p] > 0.0, 'T_C'].values[0]
|
250
|
+
else:
|
251
|
+
arr[i, idx + 1] = np.nan
|
252
|
+
|
253
|
+
arr[i,0] = Results[r]['Conditions']['P_bar'].loc[0]
|
254
|
+
|
255
|
+
arr2[:, 0] = np.abs(arr[:,1] - arr[:,2])
|
256
|
+
arr2[:, 1] = np.abs(arr[:,1] - arr[:,3])
|
257
|
+
arr2[:, 2] = np.abs(arr[:,2] - arr[:,3])
|
258
|
+
arr2[:,3] = np.max(arr2[:,0:2], axis = 1)
|
259
|
+
|
260
|
+
r_arr = np.hstack((arr,arr2))
|
261
|
+
|
262
|
+
out = pd.DataFrame(data = r_arr, columns = columns)
|
263
|
+
out = out.sort_values('P_bar').reset_index(drop=True)
|
264
|
+
|
265
|
+
else:
|
266
|
+
arr = np.zeros((len(Results.keys()),4))
|
267
|
+
columns = ['P_bar'] + phases + [phases[0]+' - '+phases[1]]
|
268
|
+
for i, r in enumerate(Results.keys()):
|
269
|
+
for idx, p in enumerate(phases):
|
270
|
+
if p in Results[r]['Mass'].keys():
|
271
|
+
arr[i, idx+1] = Results[r]['Conditions'].loc[Results[r]['Mass'][p] > 0.0, 'T_C'].values[0]
|
272
|
+
else:
|
273
|
+
arr[i, idx + 1] = np.nan
|
274
|
+
|
275
|
+
arr[i,0] = Results[r]['Conditions']['P_bar'].loc[0]
|
276
|
+
|
277
|
+
arr[:,3] = np.abs(arr[:,1] - arr[:,2])
|
278
|
+
|
279
|
+
out = pd.DataFrame(data = arr, columns = columns)
|
280
|
+
out = out.sort_values('P_bar').reset_index(drop=True)
|
281
|
+
|
282
|
+
if find_min:
|
283
|
+
res = findmin(out = out, P_bar = P_bar, T_cut_C = T_cut_C)
|
284
|
+
out = {'CurveMin': res, 'Output': out}
|
285
|
+
else:
|
286
|
+
out = {'Output': out}
|
287
|
+
|
288
|
+
return out, Results
|
289
|
+
|
290
|
+
def findmin(out = None, P_bar = None, T_cut_C = None):
|
291
|
+
Res = out.copy()
|
292
|
+
|
293
|
+
if '3 Phase Saturation' in list(Res.keys()):
|
294
|
+
T_cut_old = T_cut_C
|
295
|
+
T_cut_C = T_cut_C + np.nanmin(Res[4:])
|
296
|
+
Minimum = list(Res.keys())[4:]
|
297
|
+
CurveMin = {}
|
298
|
+
for m in Minimum:
|
299
|
+
if len(Res[m][~np.isnan(Res[m].values)]) > 2:
|
300
|
+
y = Res[m][(~np.isnan(Res[m].values)) & (Res[m].values < T_cut_C)].values
|
301
|
+
x = P_bar[(~np.isnan(Res[m].values)) & (Res[m].values < T_cut_C)]
|
302
|
+
|
303
|
+
try:
|
304
|
+
y_new = interpolate.UnivariateSpline(x, y, k = 3)
|
305
|
+
|
306
|
+
P_new = np.linspace(P_bar[P_bar == np.nanmin(P_bar[(~np.isnan(Res[m].values)) & (Res[m].values < T_cut_C)])],
|
307
|
+
P_bar[P_bar == np.nanmax(P_bar[(~np.isnan(Res[m].values)) & (Res[m].values < T_cut_C)])], 200)
|
308
|
+
|
309
|
+
NewMin = np.nanmin(y_new(P_new))
|
310
|
+
P_min = P_new[np.where(y_new(P_new) == NewMin)][0]
|
311
|
+
if NewMin < T_cut_old:
|
312
|
+
Test = 'Pass'
|
313
|
+
else:
|
314
|
+
Test = 'Fail'
|
315
|
+
|
316
|
+
CurveMin[m] = {'P_min': P_min, 'Res_min': NewMin, 'y_new': y_new(P_new), 'P_new': P_new, 'test': Test}
|
317
|
+
except:
|
318
|
+
try:
|
319
|
+
y_new = interpolate.UnivariateSpline(x, y, k = 2)
|
320
|
+
|
321
|
+
P_new = np.linspace(P_bar[P_bar == np.nanmin(P_bar[(~np.isnan(Res[m].values)) & (Res[m].values < T_cut_C)])],
|
322
|
+
P_bar[P_bar == np.nanmax(P_bar[(~np.isnan(Res[m].values)) & (Res[m].values < T_cut_C)])], 200)
|
323
|
+
|
324
|
+
NewMin = np.nanmin(y_new(P_new))
|
325
|
+
P_min = P_new[np.where(y_new(P_new) == NewMin)][0]
|
326
|
+
if NewMin < T_cut_old:
|
327
|
+
Test = 'Pass'
|
328
|
+
else:
|
329
|
+
Test = 'Fail'
|
330
|
+
|
331
|
+
CurveMin[m] = {'P_min': P_min, 'Res_min': NewMin, 'y_new': y_new(P_new), 'P_new': P_new, 'test': Test}
|
332
|
+
except:
|
333
|
+
CurveMin[m] = {'P_min': np.nan, 'Res_min': np.nan, 'y_new': np.nan, 'P_new': np.nan, 'test': 'Fail'}
|
334
|
+
else:
|
335
|
+
y_new = np.nan
|
336
|
+
P_new = np.nan
|
337
|
+
NewMin = np.nan
|
338
|
+
P_min = np.nan
|
339
|
+
Test = 'Fail'
|
340
|
+
CurveMin[m] = {'P_min': P_min, 'Res_min': NewMin, 'y_new': y_new, 'P_new': P_new, 'test': Test}
|
341
|
+
|
342
|
+
else:
|
343
|
+
CurveMin = {}
|
344
|
+
m = Res.keys()[3]
|
345
|
+
if len(Res[m][~np.isnan(Res[m])]) > 2:
|
346
|
+
y = Res[m][(~np.isnan(Res[m].values)) & (Res[m].values < T_cut_C*2)].values
|
347
|
+
x = P_bar[(~np.isnan(Res[m].values)) & (Res[m].values < T_cut_C*2)]
|
348
|
+
|
349
|
+
try:
|
350
|
+
y_new = interpolate.UnivariateSpline(x, y, k = 3)
|
351
|
+
except:
|
352
|
+
y_new = interpolate.UnivariateSpline(x, y, k = 2)
|
353
|
+
|
354
|
+
P_new = np.linspace(P_bar[P_bar == np.nanmin(P_bar[(~np.isnan(Res[m])) & (Res[m] < T_cut_C*2)])],
|
355
|
+
P_bar[P_bar == np.nanmax(P_bar[(~np.isnan(Res[m])) & (Res[m] < T_cut_C*2)])], 200)
|
356
|
+
|
357
|
+
NewMin = np.nanmin(y_new(P_new))
|
358
|
+
P_min = P_new[np.where(y_new(P_new) == NewMin)][0]
|
359
|
+
if NewMin < T_cut_C:
|
360
|
+
Test = 'Pass'
|
361
|
+
else:
|
362
|
+
Test = 'Fail'
|
363
|
+
else:
|
364
|
+
y_new = np.nan
|
365
|
+
P_new = np.nan
|
366
|
+
NewMin = np.nan
|
367
|
+
P_min = np.nan
|
368
|
+
Test = 'Fail'
|
369
|
+
|
370
|
+
CurveMin[m] = {'P_min': P_min, 'Res_min': NewMin, 'y_new': y_new, 'P_new': P_new, 'test': Test}
|
371
|
+
|
372
|
+
return CurveMin
|
373
|
+
|
374
|
+
|
375
|
+
def find_mineral_cosaturation(cores = None, Model = None, bulk = None, phases = None, P_bar = None, Fe3Fet_Liq = None,
|
376
|
+
H2O_Liq = None, H2O_Sat = False, T_initial_C = None, dt_C = None, T_maxdrop_C = None,
|
377
|
+
T_cut_C = None, find_range = None, find_min = None, fO2_buffer = None, fO2_offset = None):
|
27
378
|
'''
|
28
379
|
Carry out multiple calculations in parallel. Allows isobaric, polybaric and isochoric crystallisation to be performed as well as isothermal, isenthalpic or isentropic decompression. All temperature inputs/outputs are reported in degrees celcius and pressure is reported in bars.
|
29
380
|
|
@@ -621,406 +972,3 @@ def satTemperature(q, index, *, Model = None, comp = None, phases = None, T_init
|
|
621
972
|
return
|
622
973
|
|
623
974
|
|
624
|
-
# def detRange(P, Model, bulk, Results, Phases, T_initial = None, Fe3 = None, H2O = None, T_cut = None, findRange = None, cores = None):
|
625
|
-
# '''
|
626
|
-
# re-run the SatPress calculations using a higher resolution to determine the range of P (+H2O +fO2) where the maximum difference between the target saturation curve is below some reference value.
|
627
|
-
# '''
|
628
|
-
# if T_cut is None:
|
629
|
-
# T_cut = 5
|
630
|
-
#
|
631
|
-
# if T_initial is None:
|
632
|
-
# T_initial = 1200
|
633
|
-
#
|
634
|
-
# Res_key = list(Results.keys())[:-2]
|
635
|
-
#
|
636
|
-
# if Fe3 is None and H2O is None:
|
637
|
-
# P_min = np.zeros(len(Res_key))
|
638
|
-
# P_max = np.zeros(len(Res_key))
|
639
|
-
# i = 0
|
640
|
-
# for Res in Res_key:
|
641
|
-
# if len(Results[Res][np.where(Results[Res]<T_cut*2)]) > 0:
|
642
|
-
# P_min[i] = np.nanmin(P[np.where(Results[Res]<T_cut*2)])
|
643
|
-
# P_max[i] = np.nanmax(P[np.where(Results[Res]<T_cut*2)])
|
644
|
-
# else:
|
645
|
-
# P_min[i] = np.nan
|
646
|
-
# P_max[i] = np.nan
|
647
|
-
#
|
648
|
-
# i = i + 1
|
649
|
-
#
|
650
|
-
# P_start = np.nanmin(P_min)
|
651
|
-
# P_end = np.nanmax(P_max)
|
652
|
-
#
|
653
|
-
# P_space = 1 + 3*(P_end - P_start)/((np.max(P) - np.min(P))/(len(P)-1))
|
654
|
-
#
|
655
|
-
# P = np.linspace(P_start, P_end, int(P_space))
|
656
|
-
#
|
657
|
-
# with open('bulk.obj', 'wb') as f:
|
658
|
-
# pickle.dump(bulk, f)
|
659
|
-
#
|
660
|
-
# if len(Phases) == 3:
|
661
|
-
# phases[0], b_Sat, c_Sat, T_Liq, H2O_Melt = findSat(P, Model, Phases, bulk, T_initial = T_initial, dt = T_cut, T_step = T_cut, cores = cores)
|
662
|
-
# else:
|
663
|
-
# phases[0], b_Sat, T_Liq, H2O_Melt = findSat(P, Model, Phases, bulk, T_initial = T_initial, dt = T_cut, T_step = T_cut, cores = cores)
|
664
|
-
#
|
665
|
-
# # calc residuals
|
666
|
-
# if len(Phases) == 3:
|
667
|
-
# Results_new = findResiduals(phases[0], b_Sat, c_Sat = c_Sat)
|
668
|
-
# else:
|
669
|
-
# Results_new = findResiduals(phases[0], b_Sat)
|
670
|
-
#
|
671
|
-
# Results_new['H2O_sat'] = H2O_Melt
|
672
|
-
# Results_new['T_Liq'] = T_Liq
|
673
|
-
#
|
674
|
-
# for Res in Res_key:
|
675
|
-
# if len(Results_new[Res][np.where(~np.isnan(Results_new[Res]))]) > 0:
|
676
|
-
# Results_new[Res + '_min_P'] = np.nanmin(P[~np.isnan(Results_new[Res])])
|
677
|
-
# Results_new[Res + '_max_P'] = np.nanmin(P[~np.isnan(Results_new[Res])])
|
678
|
-
# else:
|
679
|
-
# Results_new[Res + '_min_P'] = np.nan
|
680
|
-
# Results_new[Res + '_max_P'] = np.nan
|
681
|
-
#
|
682
|
-
# return Results_new
|
683
|
-
#
|
684
|
-
# if Fe3 is not None and H2O is None:
|
685
|
-
# P_min = np.zeros(len(Res_key))
|
686
|
-
# P_max = np.zeros(len(Res_key))
|
687
|
-
#
|
688
|
-
# Fe3_min = np.zeros(len(Res_key))
|
689
|
-
# Fe3_max = np.zeros(len(Res_key))
|
690
|
-
#
|
691
|
-
# P_mat, Fe3_mat = np.meshgrid(P, Fe3)
|
692
|
-
#
|
693
|
-
# i = 0
|
694
|
-
# for Res in Res_key:
|
695
|
-
# if len(Results[Res][np.where(Results[Res]<T_cut*2)]) > 0:
|
696
|
-
# P_min[i] = np.nanmin(P_mat[np.where(Results[Res]<T_cut*2)])
|
697
|
-
# P_max[i] = np.nanmax(P_mat[np.where(Results[Res]<T_cut*2)])
|
698
|
-
#
|
699
|
-
# Fe3_min[i] = np.nanmin(Fe3_mat[np.where(Results[Res]<T_cut*2)])
|
700
|
-
# Fe3_max[i] = np.nanmax(Fe3_mat[np.where(Results[Res]<T_cut*2)])
|
701
|
-
# else:
|
702
|
-
#
|
703
|
-
# P_min[i] = np.nan
|
704
|
-
# P_max[i] = np.nan
|
705
|
-
#
|
706
|
-
# Fe3_min[i] = np.nan
|
707
|
-
# Fe3_max[i] = np.nan
|
708
|
-
#
|
709
|
-
# i = i + 1
|
710
|
-
#
|
711
|
-
# P_start = np.nanmin(P_min)
|
712
|
-
# P_end = np.nanmax(P_max)
|
713
|
-
#
|
714
|
-
# Fe3_start = np.nanmin(Fe3_min)
|
715
|
-
# Fe3_end = np.nanmax(Fe3_max)
|
716
|
-
#
|
717
|
-
# P = np.linspace(P_start, P_end, int(1 + 3*(P_end - P_start)/((np.max(P) - np.min(P))/(len(P)-1))))
|
718
|
-
# Fe3 = np.linspace(Fe3_start, Fe3_end, int(1 + 3*(Fe3_end - Fe3_start)/((np.max(Fe3) - np.min(Fe3))/(len(Fe3)-1))))
|
719
|
-
#
|
720
|
-
# if len(Phases) == 3:
|
721
|
-
# Res_abc_mat = np.zeros((len(Fe3), len(P)))
|
722
|
-
# Res_ac_mat = np.zeros((len(Fe3), len(P)))
|
723
|
-
# Res_bc_mat = np.zeros((len(Fe3), len(P)))
|
724
|
-
#
|
725
|
-
# Res_ab_mat = np.zeros((len(Fe3), len(P)))
|
726
|
-
# H2O_mat = np.zeros((len(Fe3), len(P)))
|
727
|
-
# T_Liq_mat = np.zeros((len(Fe3), len(P)))
|
728
|
-
#
|
729
|
-
# for i in range(len(Fe3)):
|
730
|
-
# Bulk_new = bulk.copy()
|
731
|
-
# Bulk_new[3] = Fe3[i]*((159.69/2)/71.844)*bulk[5]
|
732
|
-
# Bulk_new[5] = (1-Fe3[i])*bulk[5]
|
733
|
-
#
|
734
|
-
# with open('bulk.obj', 'wb') as f:
|
735
|
-
# pickle.dump(Bulk_new, f)
|
736
|
-
#
|
737
|
-
# if len(Phases) == 3:
|
738
|
-
# phases[0], b_Sat, c_Sat, T_Liq, H2O_Melt = findSat(P, Model, Phases, bulk, T_initial = T_initial, dt = T_cut, T_step = T_cut, cores = cores)
|
739
|
-
# else:
|
740
|
-
# phases[0], b_Sat, T_Liq, H2O_Melt = findSat(P, Model, Phases, bulk, T_initial = T_initial, dt = T_cut, T_step = T_cut, cores = cores)
|
741
|
-
#
|
742
|
-
# # calc residuals
|
743
|
-
# if len(Phases) == 3:
|
744
|
-
# Res = findResiduals(phases[0], b_Sat, c_Sat = c_Sat)
|
745
|
-
# Res_abc_mat[i, :] = Res['abc']
|
746
|
-
# Res_ac_mat[i, :] = Res['ac']
|
747
|
-
# Res_bc_mat[i, :] = Res['bc']
|
748
|
-
# else:
|
749
|
-
# Res = findResiduals(phases[0], b_Sat)
|
750
|
-
#
|
751
|
-
# T_Liq_mat[i, :] = T_Liq
|
752
|
-
# H2O_mat[i, :] = H2O_Melt
|
753
|
-
# Res_ab_mat[i, :] = Res['ab']
|
754
|
-
#
|
755
|
-
# if len(Phases) == 3:
|
756
|
-
# Results_new = {'abc': Res_abc_mat, 'ab': Res_ab_mat, 'ac': Res_ac_mat, 'bc': Res_bc_mat, 'H2O_Sat': H2O_mat, 'T_Liq': T_Liq_mat}
|
757
|
-
# else:
|
758
|
-
# Results_new = {'ab': Res_ab_mat, 'H2O_Sat': H2O_mat, 'T_Liq': T_Liq_mat}
|
759
|
-
#
|
760
|
-
# P_mat, Fe3_mat = np.meshgrid(P, Fe3)
|
761
|
-
# for Res in Res_key:
|
762
|
-
# if len(Results_new[Res][np.where(~np.isnan(Results_new[Res]))]) > 0:
|
763
|
-
# Results_new[Res + '_min_P'] = np.nanmin(P_mat[np.where(~np.isnan(Results_new[Res]))])
|
764
|
-
# Results_new[Res + '_max_P'] = np.nanmin(P_mat[np.where(~np.isnan(Results_new[Res]))])
|
765
|
-
#
|
766
|
-
# Results_new[Res + '_min_Fe3'] = np.nanmin(Fe3_mat[np.where(~np.isnan(Results_new[Res]))])
|
767
|
-
# Results_new[Res + '_max_Fe3'] = np.nanmin(Fe3_mat[np.where(~np.isnan(Results_new[Res]))])
|
768
|
-
# else:
|
769
|
-
# Results_new[Res + '_min_P'] = np.nan
|
770
|
-
# Results_new[Res + '_max_P'] = np.nan
|
771
|
-
#
|
772
|
-
# Results_new[Res + '_min_Fe3'] = np.nan
|
773
|
-
# Results_new[Res + '_max_Fe3'] = np.nan
|
774
|
-
#
|
775
|
-
# return Results_new
|
776
|
-
#
|
777
|
-
# if Fe3 is None and H2O is not None:
|
778
|
-
# P_min = np.zeros(len(Res_key))
|
779
|
-
# P_max = np.zeros(len(Res_key))
|
780
|
-
#
|
781
|
-
# H2O_min = np.zeros(len(Res_key))
|
782
|
-
# H2O_max = np.zeros(len(Res_key))
|
783
|
-
#
|
784
|
-
# P_mat, H2O_mat = np.meshgrid(P, H2O)
|
785
|
-
#
|
786
|
-
# i = 0
|
787
|
-
# for Res in Res_key:
|
788
|
-
# if len(Results[Res][np.where(Results[Res]<T_cut*2)]) > 0:
|
789
|
-
# P_min[i] = np.nanmin(P_mat[np.where(Results[Res]<T_cut*2)])
|
790
|
-
# P_max[i] = np.nanmax(P_mat[np.where(Results[Res]<T_cut*2)])
|
791
|
-
#
|
792
|
-
# H2O_min[i] = np.nanmin(H2O_mat[np.where(Results[Res]<T_cut*2)])
|
793
|
-
# H2O_max[i] = np.nanmax(H2O_mat[np.where(Results[Res]<T_cut*2)])
|
794
|
-
# else:
|
795
|
-
#
|
796
|
-
# P_min[i] = np.nan
|
797
|
-
# P_max[i] = np.nan
|
798
|
-
#
|
799
|
-
# H2O_min[i] = np.nan
|
800
|
-
# H2O_max[i] = np.nan
|
801
|
-
#
|
802
|
-
# i = i + 1
|
803
|
-
#
|
804
|
-
# P_start = np.nanmin(P_min)
|
805
|
-
# P_end = np.nanmax(P_max)
|
806
|
-
#
|
807
|
-
# H2O_start = np.nanmin(H2O_min)
|
808
|
-
# H2O_end = np.nanmax(H2O_max)
|
809
|
-
#
|
810
|
-
# P = np.linspace(P_start, P_end, int(1 + 3*(P_end - P_start)/((np.max(P) - np.min(P))/(len(P)-1))))
|
811
|
-
# H2O = np.linspace(H2O_start, H2O_end, int(1 + 3*(H2O_end - H2O_start)/((np.max(H2O) - np.min(H2O))/(len(H2O)-1))))
|
812
|
-
#
|
813
|
-
# if len(Phases) == 3:
|
814
|
-
# Res_abc_mat = np.zeros((len(H2O), len(P)))
|
815
|
-
# Res_ac_mat = np.zeros((len(H2O), len(P)))
|
816
|
-
# Res_bc_mat = np.zeros((len(H2O), len(P)))
|
817
|
-
#
|
818
|
-
# Res_ab_mat = np.zeros((len(H2O), len(P)))
|
819
|
-
# H2O_mat = np.zeros((len(H2O), len(P)))
|
820
|
-
# T_Liq_mat = np.zeros((len(H2O), len(P)))
|
821
|
-
#
|
822
|
-
# for i in range(len(H2O)):
|
823
|
-
# Bulk_new = bulk.copy()
|
824
|
-
# Bulk_new[14] = H2O[i]
|
825
|
-
#
|
826
|
-
# with open('bulk.obj', 'wb') as f:
|
827
|
-
# pickle.dump(Bulk_new, f)
|
828
|
-
#
|
829
|
-
# if len(Phases) == 3:
|
830
|
-
# phases[0], b_Sat, c_Sat, T_Liq, H2O_Melt = findSat(P, Model, Phases, bulk, T_initial = T_initial, dt = T_cut, T_step = T_cut, cores = cores)
|
831
|
-
# else:
|
832
|
-
# phases[0], b_Sat, T_Liq, H2O_Melt = findSat(P, Model, Phases, bulk, T_initial = T_initial, dt = T_cut, T_step = T_cut, cores = cores)
|
833
|
-
#
|
834
|
-
# # calc residuals
|
835
|
-
# if len(Phases) == 3:
|
836
|
-
# Res = findResiduals(phases[0], b_Sat, c_Sat = c_Sat)
|
837
|
-
# Res_abc_mat[i, :] = Res['abc']
|
838
|
-
# Res_ac_mat[i, :] = Res['ac']
|
839
|
-
# Res_bc_mat[i, :] = Res['bc']
|
840
|
-
# else:
|
841
|
-
# Res = findResiduals(phases[0], b_Sat)
|
842
|
-
#
|
843
|
-
# T_Liq_mat[i, :] = T_Liq
|
844
|
-
# H2O_mat[i, :] = H2O_Melt
|
845
|
-
# Res_ab_mat[i, :] = Res['ab']
|
846
|
-
#
|
847
|
-
# if len(Phases) == 3:
|
848
|
-
# Results_new = {'abc': Res_abc_mat, 'ab': Res_ab_mat, 'ac': Res_ac_mat, 'bc': Res_bc_mat, 'H2O_Sat': H2O_mat, 'T_Liq': T_Liq_mat}
|
849
|
-
# else:
|
850
|
-
# Results_new = {'ab': Res_ab_mat, 'H2O_Sat': H2O_mat, 'T_Liq': T_Liq_mat}
|
851
|
-
#
|
852
|
-
# P_mat, H2O_mat = np.meshgrid(P, H2O)
|
853
|
-
# for Res in Res_key:
|
854
|
-
# if len(Results_new[Res][np.where(~np.isnan(Results_new[Res]))]) > 0:
|
855
|
-
# Results_new[Res + '_min_P']= np.nanmin(P_mat[np.where(~np.isnan(Results_new[Res]))])
|
856
|
-
# Results_new[Res + '_max_P'] = np.nanmin(P_mat[np.where(~np.isnan(Results_new[Res]))])
|
857
|
-
#
|
858
|
-
# Results_new[Res + '_min_H2O'] = np.nanmin(Results_new['H2O_Sat'][np.where(~np.isnan(Results_new[Res]))])
|
859
|
-
# Results_new[Res + '_max_H2O'] = np.nanmin(Results_new['H2O_Sat'][np.where(~np.isnan(Results_new[Res]))])
|
860
|
-
# else:
|
861
|
-
# Results_new[Res + '_min_P']= np.nan
|
862
|
-
# Results_new[Res + '_max_P'] = np.nan
|
863
|
-
#
|
864
|
-
# Results_new[Res + '_min_H2O'] = np.nan
|
865
|
-
# Results_new[Res + '_max_H2O'] = np.nan
|
866
|
-
#
|
867
|
-
# return Results_new
|
868
|
-
#
|
869
|
-
# if H2O is not None and Fe3 is not None:
|
870
|
-
# Results_new = {}
|
871
|
-
# P_min = np.zeros(len(Res_key))
|
872
|
-
# P_max = np.zeros(len(Res_key))
|
873
|
-
#
|
874
|
-
# Fe3_min = np.zeros(len(Res_key))
|
875
|
-
# Fe3_max = np.zeros(len(Res_key))
|
876
|
-
#
|
877
|
-
# H2O_min = np.zeros(len(Res_key))
|
878
|
-
# H2O_max = np.zeros(len(Res_key))
|
879
|
-
#
|
880
|
-
# Fe3_mat, H2O_mat, P_mat = np.meshgrid(Fe3, H2O, P)
|
881
|
-
#
|
882
|
-
# i = 0
|
883
|
-
# for Res in Res_key:
|
884
|
-
# if len(Results[Res][np.where(Results[Res]<T_cut*2)]) > 0:
|
885
|
-
# P_min[i] = np.nanmin(P_mat[np.where(Results[Res]<T_cut*2)])
|
886
|
-
# P_max[i] = np.nanmax(P_mat[np.where(Results[Res]<T_cut*2)])
|
887
|
-
#
|
888
|
-
# H2O_min[i] = np.nanmin(H2O_mat[np.where(Results[Res]<T_cut*2)])
|
889
|
-
# H2O_max[i] = np.nanmax(H2O_mat[np.where(Results[Res]<T_cut*2)])
|
890
|
-
#
|
891
|
-
# Fe3_min[i] = np.nanmin(Fe3_mat[np.where(Results[Res]<T_cut*2)])
|
892
|
-
# Fe3_max[i] = np.nanmax(Fe3_mat[np.where(Results[Res]<T_cut*2)])
|
893
|
-
# else:
|
894
|
-
#
|
895
|
-
# P_min[i] = np.nan
|
896
|
-
# P_max[i] = np.nan
|
897
|
-
#
|
898
|
-
# H2O_min[i] = np.nan
|
899
|
-
# H2O_max[i] = np.nan
|
900
|
-
#
|
901
|
-
# Fe3_min[i] = np.nan
|
902
|
-
# Fe3_max[i] = np.nan
|
903
|
-
#
|
904
|
-
# i = i + 1
|
905
|
-
#
|
906
|
-
# if findRange == 'abc':
|
907
|
-
# P_start = P_min[0] - (P[1] - P[0])/3
|
908
|
-
# P_end = P_max[0] + (P[1] - P[0])/3
|
909
|
-
#
|
910
|
-
# H2O_start = H2O_min[0] - (H2O[1] - H2O[0])/3
|
911
|
-
# H2O_end = H2O_max[0] + (H2O[1] - H2O[0])/3
|
912
|
-
#
|
913
|
-
# Fe3_start = Fe3_min[0] - (Fe3[1] - Fe3[0])/3
|
914
|
-
# Fe3_end = Fe3_max[0] + (Fe3[1] - Fe3[0])/3
|
915
|
-
# else:
|
916
|
-
# P_start = np.nanmin(P_min)
|
917
|
-
# P_end = np.nanmax(P_max)
|
918
|
-
#
|
919
|
-
# H2O_start = np.nanmin(H2O_min)
|
920
|
-
# H2O_end = np.nanmax(H2O_max)
|
921
|
-
#
|
922
|
-
# Fe3_start = np.nanmin(Fe3_min)
|
923
|
-
# Fe3_end = np.nanmax(Fe3_max)
|
924
|
-
#
|
925
|
-
# if P_end - P_start > 0:
|
926
|
-
# P = np.linspace(P_start, P_end, int(1 + 3*(P_end - P_start)/((np.max(P) - np.min(P))/(len(P)))))
|
927
|
-
# else:
|
928
|
-
# return Results_new
|
929
|
-
#
|
930
|
-
# if H2O_end - H2O_start > 0:
|
931
|
-
# H2O = np.linspace(H2O_start, H2O_end, int(1 + 3*(H2O_end - H2O_start)/((np.max(H2O) - np.min(H2O))/(len(H2O)))))
|
932
|
-
# else:
|
933
|
-
# return Results_new
|
934
|
-
#
|
935
|
-
# if Fe3_end - Fe3_start > 0:
|
936
|
-
# Fe3 = np.linspace(Fe3_start, Fe3_end, int(1 + 3*(Fe3_end - Fe3_start)/((np.max(Fe3) - np.min(Fe3))/(len(Fe3)))))
|
937
|
-
# else:
|
938
|
-
# return Results_new
|
939
|
-
#
|
940
|
-
# if len(Phases) == 3:
|
941
|
-
# Res_abc_mat = np.zeros((len(H2O), len(Fe3), len(P)))
|
942
|
-
# Res_ac_mat = np.zeros((len(H2O), len(Fe3), len(P)))
|
943
|
-
# Res_bc_mat = np.zeros((len(H2O), len(Fe3), len(P)))
|
944
|
-
#
|
945
|
-
# Res_ab_mat = np.zeros((len(H2O), len(Fe3), len(P)))
|
946
|
-
# T_Liq_3Dmat = np.zeros((len(H2O), len(Fe3), len(P)))
|
947
|
-
# H2O_Liq_3Dmat = np.zeros((len(H2O), len(Fe3), len(P)))
|
948
|
-
#
|
949
|
-
# for i in range(len(H2O)):
|
950
|
-
# Bulk_new = bulk.copy()
|
951
|
-
# Bulk_new[14] = H2O[i]
|
952
|
-
#
|
953
|
-
# if len(Phases) == 3:
|
954
|
-
# Res_abc_mat_2D = np.zeros((len(Fe3), len(P)))
|
955
|
-
# Res_ac_mat_2D = np.zeros((len(Fe3), len(P)))
|
956
|
-
# Res_bc_mat_2D = np.zeros((len(Fe3), len(P)))
|
957
|
-
#
|
958
|
-
# Res_ab_mat_2D = np.zeros((len(Fe3), len(P)))
|
959
|
-
# T_Liq_mat_2D = np.zeros((len(Fe3), len(P)))
|
960
|
-
# H2O_Liq_mat_2D = np.zeros((len(Fe3), len(P)))
|
961
|
-
#
|
962
|
-
# for j in range(len(Fe3)):
|
963
|
-
#
|
964
|
-
# Bulk_new[3] = Fe3[j]*((159.69/2)/71.844)*bulk[5]
|
965
|
-
# Bulk_new[5] = (1-Fe3[j])*bulk[5]
|
966
|
-
#
|
967
|
-
# with open('bulk.obj', 'wb') as f:
|
968
|
-
# pickle.dump(Bulk_new, f)
|
969
|
-
#
|
970
|
-
# if len(Phases) == 3:
|
971
|
-
# phases[0], b_Sat, c_Sat, T_Liq, H2O_Melt = findSat(P, Model, Phases, Bulk_new, T_initial = T_initial, dt = T_cut, T_step = T_cut, cores = cores)
|
972
|
-
# else:
|
973
|
-
# phases[0], b_Sat, T_Liq, H2O_Melt = findSat(P, Model, Phases, Bulk_new, T_initial = T_initial, dt = T_cut, T_step = T_cut, cores = cores)
|
974
|
-
#
|
975
|
-
# # calc residuals
|
976
|
-
# if len(Phases) == 3:
|
977
|
-
# Res = findResiduals(phases[0], b_Sat, c_Sat = c_Sat)
|
978
|
-
# Res_abc_mat_2D[j, :] = Res['abc']
|
979
|
-
# Res_ac_mat_2D[j, :] = Res['ac']
|
980
|
-
# Res_bc_mat_2D[j, :] = Res['bc']
|
981
|
-
# else:
|
982
|
-
# Res = findResiduals(phases[0], b_Sat)
|
983
|
-
#
|
984
|
-
# Res_ab_mat_2D[j, :] = Res['ab']
|
985
|
-
# T_Liq_mat_2D[j, :] = T_Liq
|
986
|
-
# H2O_Liq_mat_2D[j, :] = H2O_Melt
|
987
|
-
#
|
988
|
-
# if len(Phases) == 3:
|
989
|
-
# Res_abc_mat[i,:,:] = Res_abc_mat_2D
|
990
|
-
# Res_ac_mat[i,:,:] = Res_ac_mat_2D
|
991
|
-
# Res_bc_mat[i,:,:] = Res_bc_mat_2D
|
992
|
-
#
|
993
|
-
# Res_ab_mat[i,:,:] = Res_ab_mat_2D
|
994
|
-
# T_Liq_3Dmat[i,:,:] = T_Liq_mat_2D
|
995
|
-
# H2O_Liq_3Dmat[i,:,:] = H2O_Liq_mat_2D
|
996
|
-
#
|
997
|
-
# if len(Phases) == 3:
|
998
|
-
# Results_new = {'abc': Res_abc_mat, 'ab': Res_ab_mat, 'ac': Res_ac_mat, 'bc': Res_bc_mat, 'H2O_Sat': H2O_Liq_3Dmat, 'T_Liq': T_Liq_3Dmat}
|
999
|
-
# else:
|
1000
|
-
# Results_new = {'ab': Res_ab_mat, 'H2O_Sat': H2O_Liq_3Dmat, 'T_Liq': T_Liq_3Dmat}
|
1001
|
-
#
|
1002
|
-
#
|
1003
|
-
# Fe3_mat, H2O_mat, P_mat = np.meshgrid(Fe3, H2O, P)
|
1004
|
-
#
|
1005
|
-
# for Res in Res_key:
|
1006
|
-
# if len(Results_new[Res][np.where(~np.isnan(Results_new[Res]))]) > 0:
|
1007
|
-
# Results_new[Res + '_min_P'] = np.nanmin(P_mat[np.where(~np.isnan(Results_new[Res]))])
|
1008
|
-
# Results_new[Res + '_max_P'] = np.nanmax(P_mat[np.where(~np.isnan(Results_new[Res]))])
|
1009
|
-
#
|
1010
|
-
# Results_new[Res + '_min_H2O'] = np.nanmin(Results_new['H2O_Sat'][np.where(~np.isnan(Results_new[Res]))])
|
1011
|
-
# Results_new[Res + '_max_H2O'] = np.nanmax(Results_new['H2O_Sat'][np.where(~np.isnan(Results_new[Res]))])
|
1012
|
-
#
|
1013
|
-
# Results_new[Res + '_min_Fe3'] = np.nanmin(Fe3_mat[np.where(~np.isnan(Results_new[Res]))])
|
1014
|
-
# Results_new[Res + '_max_Fe3'] = np.nanmax(Fe3_mat[np.where(~np.isnan(Results_new[Res]))])
|
1015
|
-
# else:
|
1016
|
-
# Results_new[Res + '_min_P'] = np.nan
|
1017
|
-
# Results_new[Res + '_max_P'] = np.nan
|
1018
|
-
#
|
1019
|
-
# Results_new[Res + '_min_H2O'] = np.nan
|
1020
|
-
# Results_new[Res + '_max_H2O'] = np.nan
|
1021
|
-
#
|
1022
|
-
# Results_new[Res + '_min_Fe3'] = np.nan
|
1023
|
-
# Results_new[Res + '_max_Fe3'] = np.nan
|
1024
|
-
#
|
1025
|
-
# return Results_new
|
1026
|
-
|
PetThermoTools/MELTS.py
CHANGED
@@ -299,7 +299,9 @@ def findCO2_MELTS(P_bar = None, Model = None, T_C = None, comp = None, melts = N
|
|
299
299
|
|
300
300
|
return T_Liq, H2O, CO2
|
301
301
|
|
302
|
-
def findLiq_MELTS(P_bar = None, Model = None, T_C_init = None, comp = None, melts = None,
|
302
|
+
def findLiq_MELTS(P_bar = None, Model = None, T_C_init = None, comp = None, melts = None,
|
303
|
+
fO2_buffer = None, fO2_offset = None, Step = None, fluid_test = None,
|
304
|
+
bulk_return = None, step = None, Affinity = False):
|
303
305
|
'''
|
304
306
|
Perform a single find liquidus calculation in MELTS. WARNING! Running this function directly from the command land/jupyter notebook will initiate the MELTS C library in the main python process. Once this has been initiated the MELTS C library cannot be re-loaded and failures during the calculation will likely cause a terminal error to occur.
|
305
307
|
|
@@ -801,12 +803,12 @@ def phaseSat_MELTS(Model = None, comp = None, phases = None, T_initial_C = None,
|
|
801
803
|
|
802
804
|
return Results
|
803
805
|
|
804
|
-
def path_MELTS(Model = None, comp = None, Frac_solid = None, Frac_fluid = None,
|
805
|
-
T_C = None, T_path_C = None, T_start_C = None, T_end_C = None, dt_C = None,
|
806
|
+
def path_MELTS(Model = None, comp = None, Frac_solid = None, Frac_fluid = None, T_initial_C = 1400,
|
807
|
+
T_C = None, T_path_C = None, T_start_C = None, T_end_C = None, dt_C = None, T_maxdrop_C = None,
|
806
808
|
P_bar = None, P_path_bar = None, P_start_bar = None, P_end_bar = None, dp_bar = None,
|
807
809
|
isenthalpic = None, isentropic = None, isochoric = None, find_liquidus = None,
|
808
810
|
fO2_buffer = None, fO2_offset = None, fluid_sat = None, Crystallinity_limit = None,
|
809
|
-
Suppress = ['rutile', 'tridymite'], Suppress_except=False):
|
811
|
+
Suppress = ['rutile', 'tridymite'], Suppress_except=False, phases=None, trail = None, melts = None):
|
810
812
|
'''
|
811
813
|
Perform a single calculation in MELTS. WARNING! Running this function directly from the command land/jupyter notebook will initiate the MELTS C library in the main python process. Once this has been initiated the MELTS C library cannot be re-loaded and failures during the calculation will likely cause a terminal error to occur.
|
812
814
|
|
@@ -882,6 +884,8 @@ def path_MELTS(Model = None, comp = None, Frac_solid = None, Frac_fluid = None,
|
|
882
884
|
|
883
885
|
'''
|
884
886
|
Results = {}
|
887
|
+
if trail is not None:
|
888
|
+
trail = False
|
885
889
|
|
886
890
|
if comp is None:
|
887
891
|
raise Exception("No composition specified")
|
@@ -896,16 +900,17 @@ def path_MELTS(Model = None, comp = None, Frac_solid = None, Frac_fluid = None,
|
|
896
900
|
if T_path_C is None and T_start_C is None and find_liquidus is None:
|
897
901
|
raise Exception("Starting temperature must be specified or the liquidus must be found")
|
898
902
|
|
899
|
-
|
903
|
+
if melts is None:
|
904
|
+
from meltsdynamic import MELTSdynamic
|
900
905
|
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
906
|
+
if Model is None or Model == "MELTSv1.0.2":
|
907
|
+
melts = MELTSdynamic(1)
|
908
|
+
elif Model == "pMELTS":
|
909
|
+
melts = MELTSdynamic(2)
|
910
|
+
elif Model == "MELTSv1.1.0":
|
911
|
+
melts = MELTSdynamic(3)
|
912
|
+
elif Model == "MELTSv1.2.0":
|
913
|
+
melts = MELTSdynamic(4)
|
909
914
|
|
910
915
|
bulk = [comp['SiO2_Liq'], comp['TiO2_Liq'], comp['Al2O3_Liq'], comp['Fe3Fet_Liq']*((159.59/2)/71.844)*comp['FeOt_Liq'], comp['Cr2O3_Liq'], (1- comp['Fe3Fet_Liq'])*comp['FeOt_Liq'], comp['MnO_Liq'], comp['MgO_Liq'], 0.0, 0.0, comp['CaO_Liq'], comp['Na2O_Liq'], comp['K2O_Liq'], comp['P2O5_Liq'], comp['H2O_Liq'], comp['CO2_Liq'], 0.0, 0.0, 0.0]
|
911
916
|
bulk = list(100*np.array(bulk)/np.sum(bulk))
|
@@ -946,18 +951,27 @@ def path_MELTS(Model = None, comp = None, Frac_solid = None, Frac_fluid = None,
|
|
946
951
|
if P_path_bar is not None:
|
947
952
|
try:
|
948
953
|
if type(P_path_bar) == np.ndarray:
|
949
|
-
Liq_Results = findLiq_MELTS(P_bar = P_path_bar[0], comp = bulk, melts = melts, fO2_buffer = fO2_buffer, fO2_offset = fO2_offset, T_C_init =
|
954
|
+
Liq_Results = findLiq_MELTS(P_bar = P_path_bar[0], comp = bulk, melts = melts, fO2_buffer = fO2_buffer, fO2_offset = fO2_offset, T_C_init = T_initial_C)
|
950
955
|
else:
|
951
|
-
Liq_Results = findLiq_MELTS(P_bar = P_path_bar, comp = bulk, melts = melts, fO2_buffer = fO2_buffer, fO2_offset = fO2_offset, T_C_init =
|
956
|
+
Liq_Results = findLiq_MELTS(P_bar = P_path_bar, comp = bulk, melts = melts, fO2_buffer = fO2_buffer, fO2_offset = fO2_offset, T_C_init = T_initial_C)
|
952
957
|
except:
|
953
|
-
|
958
|
+
if trail is not None:
|
959
|
+
return Results, trail
|
960
|
+
else:
|
961
|
+
return Results
|
954
962
|
elif P_start_bar is not None:
|
955
963
|
try:
|
956
|
-
Liq_Results = findLiq_MELTS(P_bar = P_start_bar, comp = bulk, melts = melts, fO2_buffer = fO2_buffer, fO2_offset = fO2_offset, T_C_init =
|
964
|
+
Liq_Results = findLiq_MELTS(P_bar = P_start_bar, comp = bulk, melts = melts, fO2_buffer = fO2_buffer, fO2_offset = fO2_offset, T_C_init = T_initial_C)
|
957
965
|
except:
|
958
|
-
|
966
|
+
if trail is not None:
|
967
|
+
return Results, trail
|
968
|
+
else:
|
969
|
+
return Results
|
959
970
|
|
971
|
+
print(Liq_Results)
|
960
972
|
T_start_C = Liq_Results['T_Liq'] + 0.1
|
973
|
+
if T_end_C is None and T_maxdrop_C is not None:
|
974
|
+
T_end_C = T_start_C - T_maxdrop_C
|
961
975
|
|
962
976
|
else:
|
963
977
|
if fO2_buffer is not None:
|
@@ -1034,6 +1048,10 @@ def path_MELTS(Model = None, comp = None, Frac_solid = None, Frac_fluid = None,
|
|
1034
1048
|
Results['liquid1_prop'] = pd.DataFrame(data = np.zeros((length, 4)), columns = ['h', 'mass', 'v', 'rho'])
|
1035
1049
|
|
1036
1050
|
for i in range(length):
|
1051
|
+
if i == 1:
|
1052
|
+
if trail is not None:
|
1053
|
+
trail = True
|
1054
|
+
|
1037
1055
|
if type(T) == np.ndarray:
|
1038
1056
|
melts.engine.temperature = T[i]
|
1039
1057
|
if type(P) == np.ndarray:
|
@@ -1082,7 +1100,11 @@ def path_MELTS(Model = None, comp = None, Frac_solid = None, Frac_fluid = None,
|
|
1082
1100
|
else:
|
1083
1101
|
melts.engine.calcEquilibriumState(1,0)
|
1084
1102
|
except:
|
1085
|
-
|
1103
|
+
trail = False
|
1104
|
+
# if trail is not None:
|
1105
|
+
# return Results, trail
|
1106
|
+
# else:
|
1107
|
+
# return Results
|
1086
1108
|
break
|
1087
1109
|
|
1088
1110
|
if isenthalpic is not None:
|
@@ -1092,7 +1114,11 @@ def path_MELTS(Model = None, comp = None, Frac_solid = None, Frac_fluid = None,
|
|
1092
1114
|
else:
|
1093
1115
|
melts.engine.calcEquilibriumState(2,0)
|
1094
1116
|
except:
|
1095
|
-
|
1117
|
+
trail = False
|
1118
|
+
# if trail is not None:
|
1119
|
+
# return Results, trail
|
1120
|
+
# else:
|
1121
|
+
# return Results
|
1096
1122
|
break
|
1097
1123
|
|
1098
1124
|
if isentropic is not None:
|
@@ -1102,6 +1128,7 @@ def path_MELTS(Model = None, comp = None, Frac_solid = None, Frac_fluid = None,
|
|
1102
1128
|
else:
|
1103
1129
|
melts.engine.calcEquilibriumState(3,0)
|
1104
1130
|
except:
|
1131
|
+
trail = False
|
1105
1132
|
# return Results
|
1106
1133
|
break
|
1107
1134
|
|
@@ -1109,6 +1136,7 @@ def path_MELTS(Model = None, comp = None, Frac_solid = None, Frac_fluid = None,
|
|
1109
1136
|
try:
|
1110
1137
|
melts.engine.calcEquilibriumState(4,0)
|
1111
1138
|
except:
|
1139
|
+
trail = False
|
1112
1140
|
# return Results
|
1113
1141
|
break
|
1114
1142
|
|
@@ -1128,7 +1156,8 @@ def path_MELTS(Model = None, comp = None, Frac_solid = None, Frac_fluid = None,
|
|
1128
1156
|
try:
|
1129
1157
|
PhaseList = ['liquid1'] + melts.engine.solidNames
|
1130
1158
|
except:
|
1131
|
-
|
1159
|
+
trail = False
|
1160
|
+
# return Results
|
1132
1161
|
break
|
1133
1162
|
|
1134
1163
|
for phase in PhaseList:
|
@@ -1155,9 +1184,22 @@ def path_MELTS(Model = None, comp = None, Frac_solid = None, Frac_fluid = None,
|
|
1155
1184
|
if Volume/Total_volume > Crystallinity_limit:
|
1156
1185
|
break
|
1157
1186
|
|
1187
|
+
if phases is not None:
|
1188
|
+
ll = 0
|
1189
|
+
for p in phases:
|
1190
|
+
if p in Results.keys():
|
1191
|
+
ll = ll + 1
|
1192
|
+
|
1193
|
+
if ll == len(phases):
|
1194
|
+
break
|
1195
|
+
|
1158
1196
|
melts = melts.addNodeAfter()
|
1159
1197
|
|
1160
|
-
|
1198
|
+
|
1199
|
+
if trail is not None:
|
1200
|
+
return Results, trail
|
1201
|
+
else:
|
1202
|
+
return Results
|
1161
1203
|
|
1162
1204
|
def findSatPressure_MELTS_multi(Model = None, comp = None, fO2_buffer = None, fO2_offset = None, P_bar = None, T_fixed_C = None):
|
1163
1205
|
out = pd.DataFrame(columns = ['Sample_ID_Liq', 'SiO2_Liq', 'TiO2_Liq', 'Al2O3_Liq', 'Cr2O3_Liq', 'FeOt_Liq', 'MnO_Liq', 'MgO_Liq', 'CaO_Liq', 'Na2O_Liq', 'K2O_Liq', 'P2O5_Liq', 'H2O_Liq', 'CO2_Liq', 'Fe3Fet_Liq', 'P_bar', 'T_Liq'])
|
PetThermoTools/Plotting.py
CHANGED
@@ -131,12 +131,20 @@ def plot_surfaces(Results = None, P_bar = None, phases = None, H2O_Liq = None):
|
|
131
131
|
a.set_xlabel('P (bars)')
|
132
132
|
a.set_ylabel('T ($\degree$C)')
|
133
133
|
for i in range(len(phases)):
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
134
|
+
try:
|
135
|
+
if i == 0:
|
136
|
+
a.plot(P_bar, Results['Output'][phases[0]], '-r', linewidth = 2, label = phases[i])
|
137
|
+
if i == 1:
|
138
|
+
a.plot(P_bar, Results['Output'][phases[1]], '-b', linewidth = 2, label = phases[i])
|
139
|
+
if i == 2:
|
140
|
+
a.plot(P_bar, Results['Output'][phases[2]], '-k', linewidth = 2, label = phases[i])
|
141
|
+
except:
|
142
|
+
if i == 0:
|
143
|
+
a.plot(P_bar, Results[phases[0]][0,0,:], '-r', linewidth = 2, label = phases[i])
|
144
|
+
if i == 1:
|
145
|
+
a.plot(P_bar, Results[phases[1]][0,0,:], '-b', linewidth = 2, label = phases[i])
|
146
|
+
if i == 2:
|
147
|
+
a.plot(P_bar, Results[phases[2]][0,0,:], '-k', linewidth = 2, label = phases[i])
|
140
148
|
|
141
149
|
a.legend()
|
142
150
|
|
@@ -184,7 +192,11 @@ def residualT_plot(Results = None, P_bar = None, phases = None, H2O_Liq = None,
|
|
184
192
|
for i in range(2):
|
185
193
|
for j in range(2):
|
186
194
|
a[i][j].set_title(Name[i,j])
|
187
|
-
|
195
|
+
try:
|
196
|
+
a[i][j].plot(P_bar, Results['Output'][m[i,j]], 'ok', markerfacecolor="b", label="original", markersize = 8)
|
197
|
+
except:
|
198
|
+
print("You are using the old find_mineral_saturation function.\n This will soon be removed, please transition to the mineral_cosaturation function.")
|
199
|
+
a[i][j].plot(P_bar, Results[m[i,j]][0,0,:], 'ok', markerfacecolor="b", label="original", markersize = 8)
|
188
200
|
if interpolate is True:
|
189
201
|
if ~np.isnan(Results['CurveMin'][m[i,j]]['P_min']):
|
190
202
|
a[i][j].plot(Results['CurveMin'][m[i,j]]['P_new'], Results['CurveMin'][m[i,j]]['y_new'],
|
PetThermoTools/_version.py
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
LICENSE
|
2
|
+
|
3
|
+
Copyright (c) [2025] [Matthew Gleeson]
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, subject to the following conditions:
|
6
|
+
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
8
|
+
|
9
|
+
Special Clause on GUI Usage
|
10
|
+
|
11
|
+
Use of PetThermoTools in graphical user interfaces (GUIs), including but not limited to applications that provide point-and-click access to PetThermoTools's functions, requires prior written permission from the author.
|
12
|
+
|
13
|
+
This requirement exists because of a broader issue in the geoscience community: tools that wrap or interface with core scientific software often receive the bulk of citations, while foundational packages like PetThermoTools go unrecognized—particularly when journals impose citation limits. PetThermoTools represents a significant and ongoing labor investment. Responsible citation and acknowledgment are necessary to support its continued development and maintenance.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
16
|
+
|
@@ -1,19 +1,20 @@
|
|
1
|
-
PetThermoTools/Barom.py,sha256=
|
1
|
+
PetThermoTools/Barom.py,sha256=chxLZCCu0I8PLw0-TWsJboxiRqQJufKyVEVLk35dzVo,40494
|
2
2
|
PetThermoTools/Compositions.py,sha256=65NzfduzWdfHJ8VmHBN1Cv7fMz7kF3QbDVLei-e4v00,1483
|
3
3
|
PetThermoTools/GenFuncs.py,sha256=u2GWqH--Wmqd0WXHxfulEAatQb6uswjl1s9SyyoHSa8,16412
|
4
4
|
PetThermoTools/Holland.py,sha256=udBFeVUyTBpSfLIhx7Hy6o0I8ApNCDvwU_gZa0diY5w,7251
|
5
5
|
PetThermoTools/Installation.py,sha256=UfVOW1NZFdzMWPyID5u7t0KwvpJA0AqYohzidXIAwYs,6098
|
6
6
|
PetThermoTools/Liq.py,sha256=2kdU8r00Y20khwvPvCvLr6P7y2HEOvCH2cwrF_qw5u8,35541
|
7
|
-
PetThermoTools/MELTS.py,sha256
|
7
|
+
PetThermoTools/MELTS.py,sha256=CjUOJSUEoq4yXEojl77HgCj7aewhFDeSGt4ZGk3L3vs,73688
|
8
8
|
PetThermoTools/Melting.py,sha256=h1-KchPFw5tI2xoOyNJUfVy_TJqTtcYiHtGuInIwzio,11017
|
9
9
|
PetThermoTools/Path.py,sha256=FI_JkpCDXUVWsaKxA_PKOyKvXSzsQEBiLonGNiamcIM,33424
|
10
10
|
PetThermoTools/Path_wrappers.py,sha256=_0pBs_cK2hICxAHkYxKXICUnUEBSiUg07-qhgBeuTdc,26555
|
11
11
|
PetThermoTools/PhaseDiagrams.py,sha256=8S_BcqggBzfUbiCPcsJRWFBenGL4tcCevte3-ATQjQI,30884
|
12
|
-
PetThermoTools/Plotting.py,sha256=
|
12
|
+
PetThermoTools/Plotting.py,sha256=IMYYusZy6REQATG9NI3dGlGs6h3vQ48aJHkZnHmSDDY,28924
|
13
13
|
PetThermoTools/Saturation.py,sha256=XXY6fKVouQM3RLgQgXur4xSq7_uGp7bCw_k7NNlWYi8,14095
|
14
14
|
PetThermoTools/__init__.py,sha256=PbiwQj_mNNEwuIZOLETmtMMshiXa50wjCA6mfvpOpOs,2393
|
15
|
-
PetThermoTools/_version.py,sha256=
|
16
|
-
PetThermoTools-0.2.
|
17
|
-
PetThermoTools-0.2.
|
18
|
-
PetThermoTools-0.2.
|
19
|
-
PetThermoTools-0.2.
|
15
|
+
PetThermoTools/_version.py,sha256=ZyVKd7JEm_88aeNoezRSEHfFgAtOuHaYQWt8wmb4mgc,296
|
16
|
+
PetThermoTools-0.2.34.dist-info/LICENSE.txt,sha256=-mkx4iEw8Pk1RZUvncBhGLW87Uur5JB7FBQtOmX-VP0,1752
|
17
|
+
PetThermoTools-0.2.34.dist-info/METADATA,sha256=okQdLGfhCpo2f211FXt6szwCr2KrRHpqxAVKSl6kPec,796
|
18
|
+
PetThermoTools-0.2.34.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
19
|
+
PetThermoTools-0.2.34.dist-info/top_level.txt,sha256=IqK8iYBR3YJozzMOTRZ8x8mU2k6x8ycoMBxZTm-I06U,15
|
20
|
+
PetThermoTools-0.2.34.dist-info/RECORD,,
|
File without changes
|
File without changes
|