PetThermoTools 0.2.31__py3-none-any.whl → 0.2.33__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 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,212 @@ from tqdm.notebook import tqdm, trange
23
24
  from scipy import interpolate
24
25
  from shapely.geometry import MultiPoint, Point, Polygon
25
26
 
26
- def find_mineral_cosaturation(cores = None, Model = None, bulk = None, phases = None, P_bar = None, Fe3Fet_Liq = None, H2O_Liq = None, H2O_Sat = False, T_initial_C = None, dt_C = None, T_maxdrop_C = None, T_cut_C = None, find_range = None, find_min = None, fO2_buffer = None, fO2_offset = None):
27
+ from functools import partial
28
+ import concurrent.futures
29
+
30
+
31
+ def run_melts_single(Pin, Model, comp, T_maxdrop_C, dt_C, T_initial_C,
32
+ fO2_buffer, fO2_offset, H2O_Sat, phases):
33
+ try:
34
+ return path_MELTS(
35
+ Model=Model,
36
+ comp=comp,
37
+ T_maxdrop_C=T_maxdrop_C,
38
+ dt_C=dt_C,
39
+ T_initial_C=T_initial_C,
40
+ P_bar=Pin,
41
+ find_liquidus=True,
42
+ fO2_buffer=fO2_buffer,
43
+ fO2_offset=fO2_offset,
44
+ fluid_sat=H2O_Sat,
45
+ Suppress=['rutile', 'tridymite'],
46
+ phases=phases
47
+ )
48
+ except Exception as e:
49
+ print(f"Failed at {Pin} bar: {e}")
50
+ return None
51
+
52
+ def mineral_cosaturation(Model="MELTSv1.0.2", cores=int(np.floor(multiprocessing.cpu_count()/2)), bulk=None,
53
+ phases=['quartz1', 'alkali-feldspar1', 'plagioclase1'],
54
+ P_bar=np.linspace(250, 5000, 32), Fe3Fet_init=None, H2O_init=None,
55
+ CO2_init=None, H2O_Sat=False, T_initial_C=None, dt_C=2,
56
+ T_maxdrop_C=50, T_cut_C=20, find_range=True,
57
+ find_min=True, fO2_buffer=None, fO2_offset=0.0, timeout = 30):
58
+
59
+ comp = bulk.copy()
60
+ if H2O_Sat:
61
+ comp['H2O_Liq'] = 20
62
+
63
+ comp = comp_fix(Model=Model, comp=comp, Fe3Fet_Liq=Fe3Fet_init,
64
+ H2O_Liq=H2O_init, CO2_Liq=CO2_init)
65
+
66
+ run_partial = partial(run_melts_single,
67
+ Model=Model, comp=comp, T_maxdrop_C=T_maxdrop_C,
68
+ dt_C=dt_C, T_initial_C=T_initial_C,
69
+ fO2_buffer=fO2_buffer, fO2_offset=fO2_offset,
70
+ H2O_Sat=H2O_Sat, phases=phases)
71
+
72
+ results = {}
73
+ with concurrent.futures.ProcessPoolExecutor(max_workers=cores) as executor:
74
+ futures = {executor.submit(run_partial, p): i for i, p in enumerate(P_bar)}
75
+
76
+ done, not_done = concurrent.futures.wait(
77
+ futures.keys(), timeout=timeout, return_when=concurrent.futures.ALL_COMPLETED
78
+ )
79
+
80
+ for future in done:
81
+ i = futures[future]
82
+ try:
83
+ results[f"P = {P_bar[i]:.2f} bars"] = future.result()
84
+ except Exception as e:
85
+ print(f"Failure at {P_bar[i]} bar: {e}")
86
+ results[f"P = {P_bar[i]:.2f} bars"] = {}
87
+
88
+ for future in not_done:
89
+ i = futures[future]
90
+ print(f"Timeout at {P_bar[i]} bar. Either the calculation was slow (increase timeout) or it failed.")
91
+ results[f"P = {P_bar[i]:.2f} bars"] = {}
92
+ future.cancel() # Cancel if still running
93
+
94
+ Results = stich(Res=results, multi=True, Model=Model)
95
+
96
+ ## determine the offset between the phases
97
+ if len(phases) == 3:
98
+ arr = np.zeros((len(Results.keys()), 4))
99
+ arr2 = np.zeros((len(Results.keys()), 4))
100
+ columns = ['P_bar'] + phases + [phases[0] + ' - ' + phases[1], phases[0] + ' - ' + phases[2], phases[1] + ' - ' + phases[2], '3 Phase Saturation']
101
+ for i, r in enumerate(Results.keys()):
102
+ for idx, p in enumerate(phases):
103
+ if p in Results[r]['Mass'].keys():
104
+ arr[i, idx+1] = Results[r]['Conditions'].loc[Results[r]['Mass'][p] > 0.0, 'T_C'].values[0]
105
+ else:
106
+ arr[i, idx + 1] = np.nan
107
+
108
+ arr[i,0] = Results[r]['Conditions']['P_bar'].loc[0]
109
+
110
+ arr2[:, 0] = np.abs(arr[:,1] - arr[:,2])
111
+ arr2[:, 1] = np.abs(arr[:,1] - arr[:,3])
112
+ arr2[:, 2] = np.abs(arr[:,2] - arr[:,3])
113
+ arr2[:,3] = np.max(arr2[:,0:2], axis = 1)
114
+
115
+ r_arr = np.hstack((arr,arr2))
116
+
117
+ out = pd.DataFrame(data = r_arr, columns = columns)
118
+ out = out.sort_values('P_bar').reset_index(drop=True)
119
+
120
+ else:
121
+ arr = np.zeros((len(Results.keys()),4))
122
+ columns = ['P_bar'] + phases + [phases[0]+' - '+phases[1]]
123
+ for i, r in enumerate(Results.keys()):
124
+ for idx, p in enumerate(phases):
125
+ if p in Results[r]['Mass'].keys():
126
+ arr[i, idx+1] = Results[r]['Conditions'].loc[Results[r]['Mass'][p] > 0.0, 'T_C'].values[0]
127
+ else:
128
+ arr[i, idx + 1] = np.nan
129
+
130
+ arr[i,0] = Results[r]['Conditions']['P_bar'].loc[0]
131
+
132
+ arr[:,3] = np.abs(arr[:,1] - arr[:,2])
133
+
134
+ out = pd.DataFrame(data = r_arr, columns = columns)
135
+ out = out.sort_values('P_bar').reset_index(drop=True)
136
+
137
+ if find_min:
138
+ res = findmin(out = out, P_bar = P_bar, T_cut_C = T_cut_C)
139
+ out = {'CurveMin': res, 'Output': out}
140
+ else:
141
+ out = {'Output': out}
142
+
143
+ return out, Results
144
+
145
+ def findmin(out = None, P_bar = None, T_cut_C = None):
146
+ Res = out.copy()
147
+
148
+ if '3 Phase Saturation' in list(Res.keys()):
149
+ T_cut_old = T_cut_C
150
+ T_cut_C = T_cut_C + np.nanmin(Res[4:])
151
+ Minimum = list(Res.keys())[4:]
152
+ CurveMin = {}
153
+ for m in Minimum:
154
+ if len(Res[m][~np.isnan(Res[m].values)]) > 2:
155
+ y = Res[m][(~np.isnan(Res[m].values)) & (Res[m].values < T_cut_C)].values
156
+ x = P_bar[(~np.isnan(Res[m].values)) & (Res[m].values < T_cut_C)]
157
+
158
+ try:
159
+ y_new = interpolate.UnivariateSpline(x, y, k = 3)
160
+
161
+ P_new = np.linspace(P_bar[P_bar == np.nanmin(P_bar[(~np.isnan(Res[m].values)) & (Res[m].values < T_cut_C)])],
162
+ P_bar[P_bar == np.nanmax(P_bar[(~np.isnan(Res[m].values)) & (Res[m].values < T_cut_C)])], 200)
163
+
164
+ NewMin = np.nanmin(y_new(P_new))
165
+ P_min = P_new[np.where(y_new(P_new) == NewMin)][0]
166
+ if NewMin < T_cut_old:
167
+ Test = 'Pass'
168
+ else:
169
+ Test = 'Fail'
170
+
171
+ CurveMin[m] = {'P_min': P_min, 'Res_min': NewMin, 'y_new': y_new(P_new), 'P_new': P_new, 'test': Test}
172
+ except:
173
+ try:
174
+ y_new = interpolate.UnivariateSpline(x, y, k = 2)
175
+
176
+ P_new = np.linspace(P_bar[P_bar == np.nanmin(P_bar[(~np.isnan(Res[m].values)) & (Res[m].values < T_cut_C)])],
177
+ P_bar[P_bar == np.nanmax(P_bar[(~np.isnan(Res[m].values)) & (Res[m].values < T_cut_C)])], 200)
178
+
179
+ NewMin = np.nanmin(y_new(P_new))
180
+ P_min = P_new[np.where(y_new(P_new) == NewMin)][0]
181
+ if NewMin < T_cut_old:
182
+ Test = 'Pass'
183
+ else:
184
+ Test = 'Fail'
185
+
186
+ CurveMin[m] = {'P_min': P_min, 'Res_min': NewMin, 'y_new': y_new(P_new), 'P_new': P_new, 'test': Test}
187
+ except:
188
+ CurveMin[m] = {'P_min': np.nan, 'Res_min': np.nan, 'y_new': np.nan, 'P_new': np.nan, 'test': 'Fail'}
189
+ else:
190
+ y_new = np.nan
191
+ P_new = np.nan
192
+ NewMin = np.nan
193
+ P_min = np.nan
194
+ Test = 'Fail'
195
+ CurveMin[m] = {'P_min': P_min, 'Res_min': NewMin, 'y_new': y_new, 'P_new': P_new, 'test': Test}
196
+
197
+ else:
198
+ CurveMin = {}
199
+ m = Res.keys()[3]
200
+ if len(Res[m][~np.isnan(Res[m])]) > 2:
201
+ y = Res[m][(~np.isnan(Res[m].values)) & (Res[m].values < T_cut_C*2)].values
202
+ x = P_bar[(~np.isnan(Res[m].values)) & (Res[m].values < T_cut_C*2)]
203
+
204
+ try:
205
+ y_new = interpolate.UnivariateSpline(x, y, k = 3)
206
+ except:
207
+ y_new = interpolate.UnivariateSpline(x, y, k = 2)
208
+
209
+ P_new = np.linspace(P_bar[P_bar == np.nanmin(P_bar[(~np.isnan(Res[m])) & (Res[m] < T_cut_C*2)])],
210
+ P_bar[P_bar == np.nanmax(P_bar[(~np.isnan(Res[m])) & (Res[m] < T_cut_C*2)])], 200)
211
+
212
+ NewMin = np.nanmin(y_new(P_new))
213
+ P_min = P_new[np.where(y_new(P_new) == NewMin)][0]
214
+ if NewMin < T_cut_C:
215
+ Test = 'Pass'
216
+ else:
217
+ Test = 'Fail'
218
+ else:
219
+ y_new = np.nan
220
+ P_new = np.nan
221
+ NewMin = np.nan
222
+ P_min = np.nan
223
+ Test = 'Fail'
224
+
225
+ CurveMin[m] = {'P_min': P_min, 'Res_min': NewMin, 'y_new': y_new, 'P_new': P_new, 'test': Test}
226
+
227
+ return CurveMin
228
+
229
+
230
+ def find_mineral_cosaturation(cores = None, Model = None, bulk = None, phases = None, P_bar = None, Fe3Fet_Liq = None,
231
+ H2O_Liq = None, H2O_Sat = False, T_initial_C = None, dt_C = None, T_maxdrop_C = None,
232
+ T_cut_C = None, find_range = None, find_min = None, fO2_buffer = None, fO2_offset = None):
27
233
  '''
28
234
  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
235
 
@@ -621,406 +827,3 @@ def satTemperature(q, index, *, Model = None, comp = None, phases = None, T_init
621
827
  return
622
828
 
623
829
 
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/Liq.py CHANGED
@@ -366,12 +366,15 @@ def equilibrate_multi(cores = None, Model = None, bulk = None, T_C = None, P_bar
366
366
  # Affinity = Af_Combined.copy()
367
367
  return Combined
368
368
  else:
369
- import julia
370
- from julia.api import Julia
371
- jl = Julia(compiled_modules=False)
372
- from julia import MAGEMinCalc
373
- # Output = MM.equilibrate_multi(P_bar = P_bar, T_C = T_C, comp = comp)
374
-
369
+ # import julia
370
+ # from julia.api import Julia
371
+ # jl = Julia(compiled_modules=False)
372
+ # from julia import MAGEMinCalc
373
+ ## Output = MM.equilibrate_multi(P_bar = P_bar, T_C = T_C, comp = comp)
374
+ from juliacall import Main as jl, convert as jlconvert
375
+
376
+ jl.seval("using MAGEMinCalc")
377
+
375
378
  comp['O'] = comp['Fe3Fet_Liq']*(((159.59/2)/71.844)*comp['FeOt_Liq'] - comp['FeOt_Liq'])
376
379
 
377
380
  if Model == "Weller2024":
@@ -380,8 +383,19 @@ def equilibrate_multi(cores = None, Model = None, bulk = None, T_C = None, P_bar
380
383
  bulk = comp[['SiO2_Liq', 'Al2O3_Liq', 'CaO_Liq', 'MgO_Liq', 'FeOt_Liq', 'K2O_Liq', 'Na2O_Liq', 'TiO2_Liq', 'O', 'Cr2O3_Liq', 'H2O_Liq']].astype(float).values
381
384
 
382
385
  print(np.shape(bulk))
386
+ bulk_jl = jl.seval("collect")(bulk)
387
+
388
+ if type(T_C) == np.ndarray:
389
+ T_C = jl.seval("collect")(T_C)
390
+ if type(P_bar) == np.ndarray:
391
+ P_kbar = jl.seval("collect")(P_bar/1000.0)
392
+ else:
393
+ P_kbar = P_bar/1000.0
394
+ if type(fO2_offset) == np.ndarray:
395
+ fO2_offset = jl.seval("collect")(fO2_offset)
383
396
 
384
- Output = MAGEMinCalc.equilibrate(bulk = bulk, P_kbar = P_bar/1000.0, T_C = T_C, fo2_buffer = fO2_buffer, fo2_offset = fO2_offset, Model = Model)
397
+ Output = jl.MAGEMinCalc.equilibrate(bulk = bulk_jl, P_kbar = P_kbar, T_C = T_C, fo2_buffer = fO2_buffer, fo2_offset = fO2_offset, Model = Model)
398
+ Output = dict(Output)
385
399
  Combined = stich(Output, Model = Model)
386
400
 
387
401
  if copy_columns is not None:
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, fO2_buffer = None, fO2_offset = None, Step = None, fluid_test = None, bulk_return = None, step = None, Affinity = False):
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):
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
 
@@ -946,18 +948,21 @@ def path_MELTS(Model = None, comp = None, Frac_solid = None, Frac_fluid = None,
946
948
  if P_path_bar is not None:
947
949
  try:
948
950
  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 = 1400)
951
+ 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
952
  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 = 1400)
953
+ 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
954
  except:
953
955
  return Results
954
956
  elif P_start_bar is not None:
955
957
  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 = 1400)
958
+ 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
959
  except:
958
960
  return Results
959
961
 
962
+ print(Liq_Results)
960
963
  T_start_C = Liq_Results['T_Liq'] + 0.1
964
+ if T_end_C is None and T_maxdrop_C is not None:
965
+ T_end_C = T_start_C - T_maxdrop_C
961
966
 
962
967
  else:
963
968
  if fO2_buffer is not None:
@@ -1155,6 +1160,15 @@ def path_MELTS(Model = None, comp = None, Frac_solid = None, Frac_fluid = None,
1155
1160
  if Volume/Total_volume > Crystallinity_limit:
1156
1161
  break
1157
1162
 
1163
+ if phases is not None:
1164
+ ll = 0
1165
+ for p in phases:
1166
+ if p in Results.keys():
1167
+ ll = ll + 1
1168
+
1169
+ if ll == len(phases):
1170
+ break
1171
+
1158
1172
  melts = melts.addNodeAfter()
1159
1173
 
1160
1174
  return Results
PetThermoTools/Melting.py CHANGED
@@ -171,8 +171,9 @@ def AdiabaticMelt(q, index, *, Model = None, comp_1 = None, comp_2 = None, comp_
171
171
  return
172
172
 
173
173
  if Model == "Holland":
174
- import pyMAGEMINcalc as MM
175
- Results = MM.AdiabaticDecompressionMelting(comp = comp_1, T_p_C = Tp_C, P_start_kbar = P_start_bar/1000, P_end_kbar = P_end_bar/1000, dp_kbar = dp_bar/1000, Frac = 0)
174
+ # import pyMAGEMINcalc as MM
175
+ # Results = MM.AdiabaticDecompressionMelting(comp = comp_1, T_p_C = Tp_C, P_start_kbar = P_start_bar/1000, P_end_kbar = P_end_bar/1000, dp_kbar = dp_bar/1000, Frac = 0)
176
+ print('Note that the ability to use MAGEMin to performed adiabatic decompression melting in PetThermoTools has been temporarily disabled. The underlying issue will be fixed soon and this funciton will once again become available.')
176
177
  q.put([Results, index])
177
178
  return
178
179
 
PetThermoTools/Path.py CHANGED
@@ -201,7 +201,7 @@ def multi_path(cores = None, Model = None, bulk = None, comp = None, Frac_solid
201
201
 
202
202
  qs = []
203
203
  q = Queue()
204
-
204
+
205
205
  # perform calculation if only 1 calculation is specified
206
206
  if One == 1:
207
207
  if Print_suppress is None:
@@ -374,6 +374,7 @@ def multi_path(cores = None, Model = None, bulk = None, comp = None, Frac_solid
374
374
  if Print_suppress is None:
375
375
  print(" Complete (time taken = " + str(round(time.time() - s,2)) + " seconds)", end = "\n", flush = True)
376
376
 
377
+
377
378
  Results = {}
378
379
  Out = {}
379
380
  for i in range(len(qs)):
@@ -452,7 +453,6 @@ def multi_path(cores = None, Model = None, bulk = None, comp = None, Frac_solid
452
453
 
453
454
  #if "MELTS" in Model:
454
455
  Results = stich(Results, multi = True, Model = Model, Frac_fluid = Frac_fluid, Frac_solid = Frac_solid)
455
-
456
456
 
457
457
  for r in Results:
458
458
  i = int(r.split('=')[1].strip())
@@ -625,21 +625,41 @@ def path(q, index, *, Model = None, comp = None, Frac_solid = None, Frac_fluid =
625
625
  return
626
626
 
627
627
  if "MELTS" not in Model:
628
- import julia
629
- from julia.api import Julia
630
- jl = Julia(compiled_modules=False)
631
- from julia import MAGEMinCalc
632
- # import pyMAGEMINcalc as MM
633
- # try:
634
- # Results = MM.path(Model = Model, comp = comp, Frac_solid = Frac_solid, Frac_fluid = Frac_fluid, T_C = T_C, T_path_C = T_path_C, T_start_C = T_start_C, T_end_C = T_end_C, dt_C = dt_C, P_bar = P_bar, P_path_bar = P_path_bar, P_start_bar = P_start_bar, P_end_bar = P_end_bar, dp_bar = dp_bar, find_liquidus = find_liquidus, fO2_buffer = fO2_buffer, fO2_offset = fO2_offset)
628
+ # import julia
629
+ # from julia.api import Julia
630
+ # jl = Julia(compiled_modules=False)
631
+ # from julia import MAGEMinCalc
632
+ # # import pyMAGEMINcalc as MM
633
+ # # try:
634
+ # # Results = MM.path(Model = Model, comp = comp, Frac_solid = Frac_solid, Frac_fluid = Frac_fluid, T_C = T_C, T_path_C = T_path_C, T_start_C = T_start_C, T_end_C = T_end_C, dt_C = dt_C, P_bar = P_bar, P_path_bar = P_path_bar, P_start_bar = P_start_bar, P_end_bar = P_end_bar, dp_bar = dp_bar, find_liquidus = find_liquidus, fO2_buffer = fO2_buffer, fO2_offset = fO2_offset)
635
+ # if Frac_solid is None:
636
+ # Frac_solid = False
637
+
638
+ # Results = MAGEMinCalc.path(comp = comp, T_start_C = T_start_C, T_end_C = T_end_C, dt_C = dt_C,
639
+ # T_C = T_C, P_start_bar = P_start_bar, P_end_bar = P_end_bar, dp_bar = dp_bar,
640
+ # P_bar = P_bar, T_path_C = T_path_C, P_path_bar = P_path_bar, frac_xtal = Frac_solid,
641
+ # Model = Model, fo2_buffer = fO2_buffer, fo2_offset = fO2_offset, find_liquidus = find_liquidus)
642
+ # q.put([Results, index])
643
+
644
+ # import julia
645
+ from juliacall import Main as jl, convert as jlconvert
646
+
647
+ jl.seval("using MAGEMinCalc")
648
+
635
649
  if Frac_solid is None:
636
650
  Frac_solid = False
637
-
638
- Results = MAGEMinCalc.path(comp = comp, T_start_C = T_start_C, T_end_C = T_end_C, dt_C = dt_C,
639
- T_C = T_C, P_start_bar = P_start_bar, P_end_bar = P_end_bar, dp_bar = dp_bar,
640
- P_bar = P_bar, T_path_C = T_path_C, P_path_bar = P_path_bar, frac_xtal = Frac_solid,
641
- Model = Model, fo2_buffer = fO2_buffer, fo2_offset = fO2_offset, find_liquidus = find_liquidus)
642
- q.put([Results, index])
651
+
652
+ comp_julia = jl.seval("Dict")(comp)
653
+
654
+ Results = jl.MAGEMinCalc.path(
655
+ comp=comp_julia, T_start_C=T_start_C, T_end_C=T_end_C, dt_C=dt_C,
656
+ T_C=T_C, P_start_bar=P_start_bar, P_end_bar=P_end_bar, dp_bar=dp_bar,
657
+ P_bar=P_bar, T_path_C=T_path_C, P_path_bar=P_path_bar, frac_xtal=Frac_solid,
658
+ Model=Model, fo2_buffer=fO2_buffer, fo2_offset=fO2_offset, find_liquidus=find_liquidus
659
+ )
660
+ # Results = jl.pyconvert(dict, Results)
661
+ Results_df = dict(Results)
662
+ q.put([Results_df, index])
643
663
  # except:
644
664
  # q.put([])
645
665
  # return
@@ -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
- if i == 0:
135
- a.plot(P_bar, Results[phases[0]][0,0,:], '-r', linewidth = 2, label = phases[i])
136
- if i == 1:
137
- a.plot(P_bar, Results[phases[1]][0,0,:], '-b', linewidth = 2, label = phases[i])
138
- if i == 2:
139
- a.plot(P_bar, Results[phases[2]][0,0,:], '-k', linewidth = 2, label = phases[i])
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
- a[i][j].plot(P_bar, Results[m[i,j]][0,0,:], 'ok', markerfacecolor="b", label="original", markersize = 8)
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'],
@@ -5,4 +5,4 @@
5
5
  # 1) we don't load dependencies by storing it in __init__.py
6
6
  # 2) we can import it in setup.py for the same reason
7
7
  # 3) we can import it into your module
8
- __version__ = '0.2.31'
8
+ __version__ = '0.2.33'
@@ -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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PetThermoTools
3
- Version: 0.2.31
3
+ Version: 0.2.33
4
4
  Summary: PetThermoTools
5
5
  Home-page: https://github.com/gleesonm1/PetThermoTools
6
6
  Author: Matthew Gleeson
@@ -0,0 +1,20 @@
1
+ PetThermoTools/Barom.py,sha256=zfRgGnqInXP1B5oG_k5ZMJH3cylHcQXWiBRz7YlQjkw,36119
2
+ PetThermoTools/Compositions.py,sha256=65NzfduzWdfHJ8VmHBN1Cv7fMz7kF3QbDVLei-e4v00,1483
3
+ PetThermoTools/GenFuncs.py,sha256=u2GWqH--Wmqd0WXHxfulEAatQb6uswjl1s9SyyoHSa8,16412
4
+ PetThermoTools/Holland.py,sha256=udBFeVUyTBpSfLIhx7Hy6o0I8ApNCDvwU_gZa0diY5w,7251
5
+ PetThermoTools/Installation.py,sha256=UfVOW1NZFdzMWPyID5u7t0KwvpJA0AqYohzidXIAwYs,6098
6
+ PetThermoTools/Liq.py,sha256=2kdU8r00Y20khwvPvCvLr6P7y2HEOvCH2cwrF_qw5u8,35541
7
+ PetThermoTools/MELTS.py,sha256=hqc5vSDwvnCyBwD7wbEOwemUNpDQGpsWdOOoVjNnMvE,72810
8
+ PetThermoTools/Melting.py,sha256=h1-KchPFw5tI2xoOyNJUfVy_TJqTtcYiHtGuInIwzio,11017
9
+ PetThermoTools/Path.py,sha256=FI_JkpCDXUVWsaKxA_PKOyKvXSzsQEBiLonGNiamcIM,33424
10
+ PetThermoTools/Path_wrappers.py,sha256=_0pBs_cK2hICxAHkYxKXICUnUEBSiUg07-qhgBeuTdc,26555
11
+ PetThermoTools/PhaseDiagrams.py,sha256=8S_BcqggBzfUbiCPcsJRWFBenGL4tcCevte3-ATQjQI,30884
12
+ PetThermoTools/Plotting.py,sha256=IMYYusZy6REQATG9NI3dGlGs6h3vQ48aJHkZnHmSDDY,28924
13
+ PetThermoTools/Saturation.py,sha256=XXY6fKVouQM3RLgQgXur4xSq7_uGp7bCw_k7NNlWYi8,14095
14
+ PetThermoTools/__init__.py,sha256=PbiwQj_mNNEwuIZOLETmtMMshiXa50wjCA6mfvpOpOs,2393
15
+ PetThermoTools/_version.py,sha256=i2Na-DPnshyTFid0Y6FmelIcA0OHEcYVuQdFt_mKzeI,296
16
+ PetThermoTools-0.2.33.dist-info/LICENSE.txt,sha256=-mkx4iEw8Pk1RZUvncBhGLW87Uur5JB7FBQtOmX-VP0,1752
17
+ PetThermoTools-0.2.33.dist-info/METADATA,sha256=MM-RsleOmZq3PfygLozR2VrdewAuBMezGJLwnGc9Km8,796
18
+ PetThermoTools-0.2.33.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
19
+ PetThermoTools-0.2.33.dist-info/top_level.txt,sha256=IqK8iYBR3YJozzMOTRZ8x8mU2k6x8ycoMBxZTm-I06U,15
20
+ PetThermoTools-0.2.33.dist-info/RECORD,,
@@ -1,19 +0,0 @@
1
- PetThermoTools/Barom.py,sha256=RmFT7HQ2htKrrnzLNBU1HiVN88LU82Am3cEKByxo_6o,44439
2
- PetThermoTools/Compositions.py,sha256=65NzfduzWdfHJ8VmHBN1Cv7fMz7kF3QbDVLei-e4v00,1483
3
- PetThermoTools/GenFuncs.py,sha256=u2GWqH--Wmqd0WXHxfulEAatQb6uswjl1s9SyyoHSa8,16412
4
- PetThermoTools/Holland.py,sha256=udBFeVUyTBpSfLIhx7Hy6o0I8ApNCDvwU_gZa0diY5w,7251
5
- PetThermoTools/Installation.py,sha256=UfVOW1NZFdzMWPyID5u7t0KwvpJA0AqYohzidXIAwYs,6098
6
- PetThermoTools/Liq.py,sha256=I-vYp2i7CpQjzoo-nZ8gQNTP5jrao6pZtmkmwLtjodY,35043
7
- PetThermoTools/MELTS.py,sha256=-nkyo3yx7dZXVnRwZhlMRGCc5SkYSm1nP3qDbLDNNyY,72354
8
- PetThermoTools/Melting.py,sha256=iQpSXXDhwfEUTlHa80-XFK1lahb_VNrLW8ISbVCE8lY,10773
9
- PetThermoTools/Path.py,sha256=RChQYqDayqc0hVugmX3j3uE1x2BvWIfcINFqcqwrRxw,32642
10
- PetThermoTools/Path_wrappers.py,sha256=_0pBs_cK2hICxAHkYxKXICUnUEBSiUg07-qhgBeuTdc,26555
11
- PetThermoTools/PhaseDiagrams.py,sha256=8S_BcqggBzfUbiCPcsJRWFBenGL4tcCevte3-ATQjQI,30884
12
- PetThermoTools/Plotting.py,sha256=biM4QJFCH6xVDpK-nG2oAIGIFFJCzBt5Uez6XzTFiGY,28107
13
- PetThermoTools/Saturation.py,sha256=XXY6fKVouQM3RLgQgXur4xSq7_uGp7bCw_k7NNlWYi8,14095
14
- PetThermoTools/__init__.py,sha256=PbiwQj_mNNEwuIZOLETmtMMshiXa50wjCA6mfvpOpOs,2393
15
- PetThermoTools/_version.py,sha256=x3oJ2coFvekDMGQwrW7LzNxduPT9SxWIZWCKamBahjQ,296
16
- PetThermoTools-0.2.31.dist-info/METADATA,sha256=TDZlBVXnbinSw2bKIR_YvA9KJqR4w2XxlqSGVEe4klg,796
17
- PetThermoTools-0.2.31.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
18
- PetThermoTools-0.2.31.dist-info/top_level.txt,sha256=IqK8iYBR3YJozzMOTRZ8x8mU2k6x8ycoMBxZTm-I06U,15
19
- PetThermoTools-0.2.31.dist-info/RECORD,,