PetThermoTools 0.2.39__py3-none-any.whl → 0.2.41__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/Path.py CHANGED
@@ -25,98 +25,100 @@ except:
25
25
  def multi_path(cores = None, Model = None, bulk = None, comp = None, Frac_solid = None, Frac_fluid = None,
26
26
  T_C = None, T_path_C = None, T_start_C = None, T_end_C = None, dt_C = None,
27
27
  P_bar = None, P_path_bar = None, P_start_bar = None, P_end_bar = None, dp_bar = None,
28
- Fe3Fet_Liq = None, H2O_Liq = None, CO2_Liq = None,
28
+ Fe3Fet_init = None, Fe3Fet_Liq = None, H2O_init = None, H2O_Liq = None, CO2_init = None, CO2_Liq = None,
29
29
  isenthalpic = None, isentropic = None, isochoric = None, find_liquidus = None,
30
30
  fO2_buffer = None, fO2_offset = None,
31
31
  Print_suppress = None, fluid_sat = None, Crystallinity_limit = None, Combined = None,
32
- label = None, timeout = None, print_label = True, Suppress = ['rutile', 'tridymite'], Suppress_except=False):
33
- '''
34
- 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.
35
-
36
- Parameters:
37
- ----------
38
- cores: int
39
- number of processes to run in parallel. Default will be determined using Multiprocessing.cpu_count().
40
-
41
- Model: string
42
- "MELTS" or "Holland". Dictates whether MELTS or MAGEMin calculations are performed. Default "MELTS".
43
- Version of melts can be specified "MELTSv1.0.2", "MELTSv1.1.0", "MELTSv1.2.0", or "pMELTS". Default "v.1.0.2".
44
-
45
- bulk or comp: Dict or pd.DataFrame
46
- Initial compositon for calculations. If type == Dict, the same initial composition will be used in all calculations.
47
-
48
- Frac_solid: True/False
49
- If True, solid phases will be removed from the system at the end of each step. Default False.
50
-
51
- Frac_fluid: True/False
52
- If True, fluid phases will be removed from the system at the end of each step. Default False.
53
-
54
- T_C: float or np.ndarray
55
- Calculation temperature - typically used when calculations are performed at a fixed T (e.g.,isothermal degassing).
56
-
57
- T_path_C: np.ndarray
58
- If a specified temperature path is to be used, T_path_C will be used to determine the T at each step of the model. If 2D, this indicates that multiple calculations with different T_path_C arrays are to be performed.
59
-
60
- T_start_C: float or np.ndarray
61
- Initial temperature used for path calculations.
62
-
63
- T_end_C: float or np.ndarray
64
- Final temperature in crystallisation calculations.
65
-
66
- dt_C: float or np.ndarray
67
- Temperature increment during crystallisation calculations.
68
-
69
- P_bar: float or np.ndarray
70
- Calculation pressure - typically used when calculations are performed at a fixed P (e.g.,isobaric crystallisation).
71
-
72
- P_path_bar: np.ndarray
73
- If a specified pressure path is to be used, P_path_bar will be used to determine the P at each step of the model. If 2D, this indicates that multiple calculations with different P_path_bar arrays are to be performed.
74
-
75
- P_start_bar: float or np.ndarray
76
- Initial pressure used for path calculations.
77
-
78
- P_end_bar: float or np.ndarray
79
- Final pressure in crystallisation calculations.
80
-
81
- dp_bar: float or np.ndarray
82
- Pressure increment during crystallisation calculations..
83
-
84
- Fe3Fet_Liq: float or np.ndarray
85
- Fe 3+/total ratio. If type(comp) == dict, and type(Fe3Fet_Liq) == np.ndarray a new DataFrame will be constructed with bulk compositions varying only in their Fe3Fet_Liq value. If comp is a pd.DataFrame, a single Fe3Fet_Liq value may be passed (float) and will be used as the Fe redox state for all starting compostions, or an array of Fe3Fet_Liq values, equal to the number of compositions specified in comp can specify a different Fe redox state for each sample. If None, the Fe redox state must be specified in the comp variable or an oxygen fugacity buffer must be chosen.
86
-
87
- H2O_Liq: float or np.ndarray
88
- H2O content of the initial melt phase. If type(comp) == dict, and type(H2O_Liq) = np.ndarray a new DataFrame will be constructed with bulk compositions varying only in their H2O_Liq value. If comp is a pd.DataFrame, a single H2O_Liq value may be passes (float) and will be used as the initial melt H2O content for all starting compositions. Alternatively, if an array of H2O_Liq values is passed, equal to the number of compositions specified in comp, a different initial melt H2O value will be passed for each sample. If None, H2O_Liq must be specified in the comp variable.
89
-
90
- isenthalpic: True/False
91
- If True, calculations will be performed at a constant enthalpy with T treated as a dependent variable.
92
-
93
- isentropic: True/False
94
- If True, calculations will be performed at a constant entropy with T treated as a dependent variable.
32
+ label = None, timeout = None, print_label = True, Suppress = ['rutile', 'tridymite'], Suppress_except=False,
33
+ multi_processing = True):
34
+ """
35
+ Perform single or multiple MELTS/MAGEMin crystallization or degassing calculations in series or parallel.
95
36
 
96
- isochoric: True/False
97
- If True, the volume of the system will be held constant instead of the pressure. Default is False.
98
-
99
- find_liquidus: True/False
100
- If True, the calculations will start with a search for the melt liquidus temperature. Default is False.
101
-
102
- fO2_buffer: string
103
- If the oxygen fugacity of the system is to be buffered during crystallisation/decompression, then an offset to a known buffer must be specified. Here the user can define the known buffer as either "FMQ" or "NNO".
104
-
105
- fO2_offset: float or np.ndarray
106
- Offset from the buffer spcified in fO2_buffer (log units).
107
-
108
- Print_suppress: True/False
109
- If True, print messages concerning the status of the thermodynamic calculations will not be displayed.
110
-
111
- Crystallinity_limit: float
112
- If value given, calculation will stop when the volume mass fraction of the system (excludin fluids) exceeds this value.
37
+ Supports isothermal, isenthalpic, isentropic, and isochoric processes over fixed or variable pressure and
38
+ temperature paths. Works with both MELTS and MAGEMin models. Automatically handles composition expansion when
39
+ using arrays for Fe3+/FeT, H2O, or CO2.
113
40
 
114
- Returns:
41
+ Parameters
115
42
  ----------
116
- Results: Dict
117
- Dictionary where each entry represents the results of a single calculation. Within the dictionary each single calculation is reported as a series of pandas DataFrames, displaying the composition and thermodynamic properties of each phase.
43
+ cores : int, optional
44
+ Number of CPU cores to use for multiprocessing. Defaults to total available.
45
+ Model : str
46
+ Thermodynamic model. MELTS variants: "MELTSv1.0.2", "MELTSv1.1.0", "MELTSv1.2.0", "pMELTS";
47
+ or MAGEMin: "Green2025", "Weller2024".
48
+ bulk or comp : dict or pd.DataFrame
49
+ Starting composition(s) for the model run(s). If `dict`, single composition for all runs.
50
+ Frac_solid : bool, optional
51
+ If True, remove solids at each step (fractional crystallization).
52
+ Frac_fluid : bool, optional
53
+ If True, remove fluids at each step.
54
+ T_C, P_bar : float or np.ndarray, optional
55
+ Fixed temperature/pressure values for isothermal/isobaric runs.
56
+ T_path_C, P_path_bar : np.ndarray or 2D array, optional
57
+ User-defined temperature/pressure paths for each model run.
58
+ T_start_C, T_end_C, dt_C : float or array, optional
59
+ Starting, ending, and increment temperature values for path calculations.
60
+ P_start_bar, P_end_bar, dp_bar : float or array, optional
61
+ Starting, ending, and increment pressure values for path calculations.
62
+ Fe3Fet_init : float or array, optional
63
+ Initial Fe3+/FeT ratio(s). Required if redox state is not specified in `comp` or `fO2_buffer`.
64
+ H2O_init, CO2_init : float or array, optional
65
+ Initial melt volatile contents. Required if not specified in `comp`.
66
+ isenthalpic, isentropic, isochoric : bool, optional
67
+ If True, applies respective thermodynamic constraint.
68
+ find_liquidus : bool, optional
69
+ If True, searches for the liquidus before starting.
70
+ fO2_buffer : {"FMQ", "NNO"}, optional
71
+ Specifies redox buffer for constraining oxygen fugacity.
72
+ fO2_offset : float or array, optional
73
+ Offset (in log units) from the specified fO2 buffer.
74
+ Print_suppress : bool, optional
75
+ If True, suppresses status messages.
76
+ fluid_sat : bool, optional
77
+ If True, starts the system at fluid saturation.
78
+ Crystallinity_limit : float, optional
79
+ Ends run when crystallinity (excluding fluids) exceeds this threshold.
80
+ Combined : unused
81
+ Placeholder for backwards compatibility.
82
+ label : str or array, optional
83
+ If provided, labels output dictionaries using `label`.
84
+ timeout : float, optional
85
+ Max allowed runtime for each subprocess (in seconds).
86
+ print_label : bool, default=True
87
+ If True, prints label with status updates.
88
+ Suppress : list of str
89
+ List of phases to exclude from results.
90
+ Suppress_except : bool
91
+ If True, `Suppress` acts as a whitelist instead of a blacklist.
92
+ multi_processing : bool
93
+ If False, run sequentially in main process.
94
+
95
+ Returns
96
+ -------
97
+ Results : dict
98
+ Dictionary with each run's label as key. Values are sub-dictionaries of phase/property DataFrames.
99
+ Includes `Input` key summarizing model configuration per run.
100
+ """
101
+ ## make sure everything is a float
102
+ T_C = to_float(T_C)
103
+ T_path_C = to_float(T_path_C)
104
+ T_start_C = to_float(T_start_C)
105
+ T_end_C = to_float(T_end_C)
106
+ dt_C = to_float(dt_C)
107
+
108
+ P_bar = to_float(P_bar)
109
+ P_path_bar = to_float(P_path_bar)
110
+ P_start_bar= to_float(P_start_bar)
111
+ P_end_bar = to_float(P_end_bar)
112
+ dp_bar = to_float(dp_bar)
113
+
114
+ Fe3Fet_init= to_float(Fe3Fet_init)
115
+ Fe3Fet_Liq = to_float(Fe3Fet_Liq)
116
+ H2O_init = to_float(H2O_init)
117
+ H2O_Liq = to_float(H2O_Liq)
118
+ CO2_init = to_float(CO2_init)
119
+ CO2_Liq = to_float(CO2_Liq)
120
+ fO2_offset = to_float(fO2_offset)
118
121
 
119
- '''
120
122
  if timeout is None:
121
123
  timeout = 180
122
124
 
@@ -141,6 +143,21 @@ def multi_path(cores = None, Model = None, bulk = None, comp = None, Frac_solid
141
143
  except:
142
144
  Warning('alphaMELTS for Python files are not on the python path. \n Please add these files to the path running \n import sys \n sys.path.append(r"insert_your_path_to_melts_here") \n You are looking for the location of the meltsdynamic.py file')
143
145
 
146
+ if H2O_Liq is not None:
147
+ print('Warning - the kwarg "H2O_Liq" will be removed from v1.0.0 onwards. Please use "H2O_init" instead.')
148
+ if H2O_init is None:
149
+ H2O_init = H2O_Liq
150
+
151
+ if CO2_Liq is not None:
152
+ print('Warning - the kwarg "CO2_Liq" will be removed from v1.0.0 onwards. Please use "CO2_init" instead.')
153
+ if CO2_init is None:
154
+ CO2_init = CO2_Liq
155
+
156
+ if Fe3Fet_Liq is not None:
157
+ print('Warning - the kwarg "Fe3Fet_Liq" will be removed from v1.0.0 onwards. Please use "Fe3Fet_init" instead.')
158
+ if Fe3Fet_init is None:
159
+ Fe3Fet_init = Fe3Fet_Liq
160
+
144
161
  # if comp is entered as a pandas series, it must first be converted to a dict
145
162
  if type(comp) == pd.core.series.Series:
146
163
  comp = comp.to_dict()
@@ -155,8 +172,8 @@ def multi_path(cores = None, Model = None, bulk = None, comp = None, Frac_solid
155
172
  fO2_buffer = "qfm"
156
173
 
157
174
  # ensure the bulk composition has the correct headers etc.
158
- comp = comp_fix(Model = Model, comp = comp, Fe3Fet_Liq = Fe3Fet_Liq, H2O_Liq = H2O_Liq, CO2_Liq = CO2_Liq)
159
-
175
+ comp = comp_fix(Model = Model, comp = comp, Fe3Fet_Liq = Fe3Fet_init, H2O_Liq = H2O_init, CO2_Liq = CO2_init)
176
+
160
177
  if type(comp) == dict:
161
178
  if comp['H2O_Liq'] == 0.0 and "MELTS" in Model:
162
179
  raise Warning("Adding small amounts of H$_{2}$O may improve the ability of MELTS to accurately reproduce the saturation of oxide minerals. Additionally, sufficient H$_{2}$O is required in the model for MELTS to predict the crystallisation of apatite, rather than whitlockite.")
@@ -213,45 +230,57 @@ def multi_path(cores = None, Model = None, bulk = None, comp = None, Frac_solid
213
230
  print("Running " + Model + " calculation...", end = "", flush = True)
214
231
  s = time.time()
215
232
 
216
- p = Process(target = path, args = (q, 1),
217
- kwargs = {'Model': Model, 'comp': comp, 'Frac_solid': Frac_solid, 'Frac_fluid': Frac_fluid,
218
- '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,
219
- '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,
220
- 'isenthalpic': isenthalpic, 'isentropic': isentropic, 'isochoric': isochoric, 'find_liquidus': find_liquidus,
221
- 'fO2_buffer': fO2_buffer, 'fO2_offset': fO2_offset, 'fluid_sat': fluid_sat, 'Crystallinity_limit': Crystallinity_limit,
222
- 'Suppress': Suppress, 'Suppress_except': Suppress_except})
223
-
224
- p.start()
225
- try:
226
- ret = q.get(timeout = 180)
227
- except:
228
- ret = []
229
-
230
- TIMEOUT = 5
231
- start = time.time()
232
- if p.is_alive():
233
- while time.time() - start <= TIMEOUT:
234
- if not p.is_alive():
235
- p.join()
233
+ if multi_processing:
234
+ p = Process(target = path, args = (q, 1),
235
+ kwargs = {'Model': Model, 'comp': comp, 'Frac_solid': Frac_solid, 'Frac_fluid': Frac_fluid,
236
+ '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,
237
+ '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,
238
+ 'isenthalpic': isenthalpic, 'isentropic': isentropic, 'isochoric': isochoric, 'find_liquidus': find_liquidus,
239
+ 'fO2_buffer': fO2_buffer, 'fO2_offset': fO2_offset, 'fluid_sat': fluid_sat, 'Crystallinity_limit': Crystallinity_limit,
240
+ 'Suppress': Suppress, 'Suppress_except': Suppress_except})
241
+
242
+ p.start()
243
+ try:
244
+ ret = q.get(timeout = 180)
245
+ except:
246
+ ret = []
247
+
248
+ TIMEOUT = 5
249
+ start = time.time()
250
+ if p.is_alive():
251
+ while time.time() - start <= TIMEOUT:
252
+ if not p.is_alive():
253
+ p.join()
254
+ p.terminate()
255
+ break
256
+ time.sleep(.1)
257
+ else:
236
258
  p.terminate()
237
- break
238
- time.sleep(.1)
259
+ p.join(5)
239
260
  else:
261
+ p.join()
240
262
  p.terminate()
241
- p.join(5)
242
- else:
243
- p.join()
244
- p.terminate()
245
263
 
246
- if Print_suppress is None:
247
- print(" Complete (time taken = " + str(round(time.time() - s,2)) + " seconds)", end = "", flush = True)
264
+ if Print_suppress is None:
265
+ print(" Complete (time taken = " + str(round(time.time() - s,2)) + " seconds)", end = "", flush = True)
248
266
 
249
- if len(ret) > 0:
250
- Results, index = ret
251
- Results = stich(Results, Model = Model, Frac_fluid = Frac_fluid, Frac_solid = Frac_solid)
252
- return Results
267
+ if len(ret) > 0:
268
+ Results, index = ret
269
+ Results = stich(Results, Model = Model, Frac_fluid = Frac_fluid, Frac_solid = Frac_solid)
270
+ return Results
271
+ else:
272
+ Results = {}
273
+ return Results
253
274
  else:
254
- Results = {}
275
+ Results = path_MELTS(Model = Model, comp = comp, Frac_solid = Frac_solid, Frac_fluid = Frac_fluid,
276
+ T_C = T_C, T_path_C = T_path_C, T_start_C = T_start_C, T_end_C = T_end_C,
277
+ dt_C = dt_C, P_bar = P_bar, P_path_bar = P_path_bar, P_start_bar = P_start_bar,
278
+ P_end_bar = P_end_bar, dp_bar = dp_bar, isenthalpic = isenthalpic,
279
+ isentropic = isentropic, isochoric = isochoric, find_liquidus = find_liquidus,
280
+ fO2_buffer = fO2_buffer, fO2_offset = fO2_offset, fluid_sat = fluid_sat,
281
+ Crystallinity_limit = Crystallinity_limit, Suppress = Suppress, Suppress_except = Suppress_except)
282
+
283
+ Results = stich(Results, Model = Model, Frac_fluid = Frac_fluid, Frac_solid = Frac_solid)
255
284
  return Results
256
285
 
257
286
  else: # perform multiple crystallisation calculations
@@ -363,7 +392,7 @@ def multi_path(cores = None, Model = None, bulk = None, comp = None, Frac_solid
363
392
  Results = stich(Res=results, multi=True, Model=Model, Frac_fluid = Frac_fluid, Frac_solid = Frac_solid)
364
393
 
365
394
  for r in Results:
366
- i = int(r.split('=')[1].strip())
395
+ i = int(r.split(' ')[1].strip())
367
396
  if type(comp) == dict:
368
397
  Results[r]['Input'] = {'Model': Model, 'comp': comp, 'Frac_solid': Frac_solid, 'Frac_fluid': Frac_fluid,
369
398
  'T_C': T_C[i], 'T_path_C': T_path_C[i], 'T_start_C': T_start_C[i], 'T_end_C': T_end_C[i], 'dt_C': dt_C[i],
@@ -391,6 +420,57 @@ def path_multi(q, index, *, Model = None, comp = None, Frac_solid = None, Frac_f
391
420
  isenthalpic = None, isentropic = None, isochoric = None, find_liquidus = None,
392
421
  fO2_buffer = None, fO2_offset = None, fluid_sat = None, Crystallinity_limit = None,
393
422
  Suppress = None, Suppress_except = None, trail = True):
423
+ """
424
+ Worker function to run a subset of crystallization/decompression models (MELTS or MAGEMin) in parallel.
425
+
426
+ This function is intended to be run in a separate process. It takes a set of indices representing model runs,
427
+ executes them using the appropriate model interface, and returns the results via a multiprocessing queue.
428
+
429
+ Parameters
430
+ ----------
431
+ q : multiprocessing.Queue
432
+ Output queue for sending back results.
433
+ index : list of int
434
+ Indices of the simulations to be run by this worker.
435
+ Model : str
436
+ The thermodynamic model ("MELTSv1.0.2", "MELTSv1.1.0", "MELTSv1.2.0", "pMELTS", or MAGEMin variant: "Green2025" or "Weller2024").
437
+ comp : dict or pd.DataFrame
438
+ Starting compositions. Either a single dictionary or a DataFrame with one row per simulation.
439
+ Frac_solid : bool
440
+ If True, removes solids at each step.
441
+ Frac_fluid : bool
442
+ If True, removes fluids at each step.
443
+ T_C, T_path_C, T_start_C, T_end_C, dt_C : float or np.ndarray
444
+ Temperature constraints or paths for each simulation.
445
+ P_bar, P_path_bar, P_start_bar, P_end_bar, dp_bar : float or np.ndarray
446
+ Pressure constraints or paths for each simulation.
447
+ isenthalpic, isentropic, isochoric : bool
448
+ Apply respective thermodynamic constraints.
449
+ find_liquidus : bool
450
+ If True, finds the liquidus temperature before starting.
451
+ fO2_buffer : str
452
+ Oxygen fugacity buffer ("FMQ" or "NNO").
453
+ fO2_offset : float or array
454
+ Offset from specified fO2 buffer in log units.
455
+ fluid_sat : bool
456
+ If True, terminates runs at fluid saturation.
457
+ Crystallinity_limit : float
458
+ Ends run when crystallinity exceeds this value.
459
+ Suppress : list of str
460
+ Phases to exclude from results.
461
+ Suppress_except : bool
462
+ If True, treat `Suppress` as a whitelist.
463
+ trail : bool
464
+ If True, include trailing properties from model output.
465
+
466
+ Returns
467
+ -------
468
+ None
469
+ The function returns results using `q.put()`:
470
+ q.put([idx, results])
471
+ where `idx` is the list of completed indices and `results` is a dictionary of output per run.
472
+ """
473
+
394
474
  results = {}
395
475
  idx = []
396
476
 
@@ -413,28 +493,48 @@ def path_multi(q, index, *, Model = None, comp = None, Frac_solid = None, Frac_f
413
493
 
414
494
  jl.seval("using MAGEMinCalc")
415
495
 
416
-
417
496
  for i in index:
418
497
  try:
419
498
  if "MELTS" in Model:
420
499
  if type(comp) == dict:
421
- Results, tr = path_MELTS(Model = Model, comp = comp, Frac_solid = Frac_solid, Frac_fluid = Frac_fluid,
422
- T_initial_C = 1400, T_C = T_C[i], T_path_C = T_path_C[i], T_start_C = T_start_C[i],
423
- T_end_C = T_end_C[i], dt_C = dt_C[i], P_bar = P_bar[i], P_path_bar = P_path_bar[i],
424
- P_start_bar = P_start_bar[i], P_end_bar = P_end_bar[i], dp_bar = dp_bar[i],
425
- isenthalpic = isenthalpic, isentropic = isentropic, isochoric = isochoric,
426
- find_liquidus = find_liquidus, fO2_buffer = fO2_buffer, fO2_offset = fO2_offset[i],
427
- fluid_sat = fluid_sat, Crystallinity_limit = Crystallinity_limit, Suppress = Suppress,
428
- Suppress_except=Suppress_except, trail = trail, melts = melts)
500
+ if trail is not None:
501
+ Results, tr = path_MELTS(Model = Model, comp = comp, Frac_solid = Frac_solid, Frac_fluid = Frac_fluid,
502
+ T_initial_C = 1400, T_C = T_C[i], T_path_C = T_path_C[i], T_start_C = T_start_C[i],
503
+ T_end_C = T_end_C[i], dt_C = dt_C[i], P_bar = P_bar[i], P_path_bar = P_path_bar[i],
504
+ P_start_bar = P_start_bar[i], P_end_bar = P_end_bar[i], dp_bar = dp_bar[i],
505
+ isenthalpic = isenthalpic, isentropic = isentropic, isochoric = isochoric,
506
+ find_liquidus = find_liquidus, fO2_buffer = fO2_buffer, fO2_offset = fO2_offset[i],
507
+ fluid_sat = fluid_sat, Crystallinity_limit = Crystallinity_limit, Suppress = Suppress,
508
+ Suppress_except=Suppress_except, trail = trail, melts = melts)
509
+ else:
510
+ Results = path_MELTS(Model = Model, comp = comp, Frac_solid = Frac_solid, Frac_fluid = Frac_fluid,
511
+ T_initial_C = 1400, T_C = T_C[i], T_path_C = T_path_C[i], T_start_C = T_start_C[i],
512
+ T_end_C = T_end_C[i], dt_C = dt_C[i], P_bar = P_bar[i], P_path_bar = P_path_bar[i],
513
+ P_start_bar = P_start_bar[i], P_end_bar = P_end_bar[i], dp_bar = dp_bar[i],
514
+ isenthalpic = isenthalpic, isentropic = isentropic, isochoric = isochoric,
515
+ find_liquidus = find_liquidus, fO2_buffer = fO2_buffer, fO2_offset = fO2_offset[i],
516
+ fluid_sat = fluid_sat, Crystallinity_limit = Crystallinity_limit, Suppress = Suppress,
517
+ Suppress_except=Suppress_except, trail = trail, melts = melts)
518
+
429
519
  else:
430
- Results, tr = path_MELTS(Model = Model, comp = comp.loc[i].to_dict(), Frac_solid = Frac_solid, Frac_fluid = Frac_fluid,
431
- T_initial_C = 1400, T_C = T_C[i], T_path_C = T_path_C[i], T_start_C = T_start_C[i],
432
- T_end_C = T_end_C[i], dt_C = dt_C[i], P_bar = P_bar[i], P_path_bar = P_path_bar[i],
433
- P_start_bar = P_start_bar[i], P_end_bar = P_end_bar[i], dp_bar = dp_bar[i],
434
- isenthalpic = isenthalpic, isentropic = isentropic, isochoric = isochoric,
435
- find_liquidus = find_liquidus, fO2_buffer = fO2_buffer, fO2_offset = fO2_offset[i],
436
- fluid_sat = fluid_sat, Crystallinity_limit = Crystallinity_limit, Suppress = Suppress,
437
- Suppress_except=Suppress_except, trail = trail, melts = melts)
520
+ if trail is not None:
521
+ Results, tr = path_MELTS(Model = Model, comp = comp.loc[i].to_dict(), Frac_solid = Frac_solid, Frac_fluid = Frac_fluid,
522
+ T_initial_C = 1400, T_C = T_C[i], T_path_C = T_path_C[i], T_start_C = T_start_C[i],
523
+ T_end_C = T_end_C[i], dt_C = dt_C[i], P_bar = P_bar[i], P_path_bar = P_path_bar[i],
524
+ P_start_bar = P_start_bar[i], P_end_bar = P_end_bar[i], dp_bar = dp_bar[i],
525
+ isenthalpic = isenthalpic, isentropic = isentropic, isochoric = isochoric,
526
+ find_liquidus = find_liquidus, fO2_buffer = fO2_buffer, fO2_offset = fO2_offset[i],
527
+ fluid_sat = fluid_sat, Crystallinity_limit = Crystallinity_limit, Suppress = Suppress,
528
+ Suppress_except=Suppress_except, trail = trail, melts = melts)
529
+ else:
530
+ Results = path_MELTS(Model = Model, comp = comp.loc[i].to_dict(), Frac_solid = Frac_solid, Frac_fluid = Frac_fluid,
531
+ T_initial_C = 1400, T_C = T_C[i], T_path_C = T_path_C[i], T_start_C = T_start_C[i],
532
+ T_end_C = T_end_C[i], dt_C = dt_C[i], P_bar = P_bar[i], P_path_bar = P_path_bar[i],
533
+ P_start_bar = P_start_bar[i], P_end_bar = P_end_bar[i], dp_bar = dp_bar[i],
534
+ isenthalpic = isenthalpic, isentropic = isentropic, isochoric = isochoric,
535
+ find_liquidus = find_liquidus, fO2_buffer = fO2_buffer, fO2_offset = fO2_offset[i],
536
+ fluid_sat = fluid_sat, Crystallinity_limit = Crystallinity_limit, Suppress = Suppress,
537
+ Suppress_except=Suppress_except, trail = trail, melts = melts)
438
538
  else:
439
539
  if fO2_offset[i] is None:
440
540
  fO2_offset[i] = 0.0
@@ -467,7 +567,7 @@ def path_multi(q, index, *, Model = None, comp = None, Frac_solid = None, Frac_f
467
567
  idx.append(i)
468
568
 
469
569
 
470
- results[f"index = {i}"] = Results
570
+ results[f"Run {i}"] = Results
471
571
 
472
572
  if tr is False:
473
573
  break