DiadFit 1.0.5__py3-none-any.whl → 1.0.8__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.
DiadFit/relaxifi.py CHANGED
@@ -162,7 +162,7 @@ class power_creep_law_constants:
162
162
  self.IgasR= 8.314 # Gas constant in J/(mol*K)
163
163
 
164
164
  # Helper function to calculate change in radius over time (dR/dt)
165
- def calculate_dR_dt(*,R_m, b_m, T_K, Pinternal_MPa, Pexternal_MPa):
165
+ def calculate_dR_dt(*, R_m, b_m, T_K, Pinternal_MPa, Pexternal_MPa):
166
166
  """
167
167
  Calculate the rate of change of inclusion radius (dR/dt) based on power law creep.
168
168
 
@@ -176,18 +176,29 @@ def calculate_dR_dt(*,R_m, b_m, T_K, Pinternal_MPa, Pexternal_MPa):
176
176
  Returns:
177
177
  - dR_dt (float): Rate of change of inclusion radius in meters per second.
178
178
  """
179
-
179
+
180
180
  pl_Cs = power_creep_law_constants()
181
- if Pinternal_MPa<Pexternal_MPa==True:
182
- S=-1
183
- else:
184
- S=1
181
+
182
+ # Ensure R_m is not zero to avoid division by zero in the final term
183
+ if R_m == 0:
184
+ raise ValueError("R_m cannot be zero")
185
+
186
+ # Avoid division by zero or very small numbers in the term (b_m**(3 / pl_Cs.n)) - (R_m**(3 / pl_Cs.n))
187
+ denominator = (b_m**(3 / pl_Cs.n)) - (R_m**(3 / pl_Cs.n))
188
+ if abs(denominator) < 1e-8: # Check if the value is too close to zero
189
+ raise ValueError("the distance to the defect (b_m) and the radii of the inclusion (R_m) are too close, causing division by zero. Please tweak these parameters!")
190
+
191
+ # Set the sign based on internal and external pressure difference
192
+ S = -1 if Pinternal_MPa < Pexternal_MPa else 1
193
+
185
194
  try:
186
- dR_dt = 2 * (S * pl_Cs.A * math.exp(-pl_Cs.Q / (pl_Cs.IgasR * T_K))) * (((R_m * b_m)**3) / (((b_m**(3 / pl_Cs.n)) - (R_m**(3 / pl_Cs.n))))**pl_Cs.n) * (((3 * abs(Pinternal_MPa - Pexternal_MPa)) / (2 * pl_Cs.n))**pl_Cs.n) / R_m**2
195
+ # Compute dR/dt with the necessary checks
196
+ dR_dt = 2 * (S * pl_Cs.A * math.exp(-pl_Cs.Q / (pl_Cs.IgasR * T_K))) * (((R_m * b_m)**3) / (denominator**pl_Cs.n)) * (((3 * abs(Pinternal_MPa - Pexternal_MPa)) / (2 * pl_Cs.n))**pl_Cs.n) / R_m**2
187
197
  return dR_dt
188
198
 
189
199
  except FloatingPointError:
190
200
  return np.nan
201
+
191
202
 
192
203
  # Helper function to numerically solve for R (uses Runge-Kutta method, orders 1-4)
193
204
  def get_R(R_m,b_m,T_K,Pinternal_MPa,Pexternal_MPa,dt_s,method='RK1'):
@@ -405,6 +416,8 @@ def stretch_in_ascent(*, R_m, b_m, T_K, ascent_rate_ms, depth_path_ini_fin_step=
405
416
 
406
417
  CO2_dens_initial, CO2_mass_initial = get_initial_CO2(R_m=R_m, T_K=T_K, P_MPa=Pinternal_MPa, EOS=EOS)
407
418
 
419
+
420
+ # This is just to initiate the code, the input values dont matter.
408
421
 
409
422
  results = pd.DataFrame([{'Time(s)': 0,
410
423
  'Step':0,
@@ -459,8 +472,28 @@ def stretch_in_ascent(*, R_m, b_m, T_K, ascent_rate_ms, depth_path_ini_fin_step=
459
472
 
460
473
  return results
461
474
 
475
+
476
+ def calculate_exponential_time_steps(totaltime_s, steps):
477
+ """
478
+ Generate exponentially spaced time steps with smaller steps at the beginning and larger steps towards the end.
479
+
480
+ Parameters:
481
+ - totaltime_s (float): The total time for the simulation.
482
+ - steps (int): The number of steps in the simulation.
483
+
484
+ Returns:
485
+ - dt_s_array (np.ndarray): Array of time intervals (dt_s) with smaller steps at the beginning.
486
+ """
487
+ linear_space = np.linspace(0, 1, steps) # Linear space from 0 to 1
488
+ non_uniform_space = np.exp(5 * (linear_space - 1)) # Exponential distribution with smaller steps at the beginning
489
+ non_uniform_space = non_uniform_space / non_uniform_space.sum() # Normalize so the sum equals 1
490
+ dt_s_array = non_uniform_space * totaltime_s # Scale to the total time
491
+
492
+ return dt_s_array
493
+
494
+
462
495
  # This function is to model stretching at fixed External Pressure (e.g., during stalling or upon eruption)
463
- def stretch_at_constant_Pext(*,R_m,b_m,T_K,EOS='SW96',Pinternal_MPa,Pexternal_MPa,totaltime_s,steps,method='RK4',report_results='fullpath',plotfig=False,update_b=False):
496
+ def stretch_at_constant_Pext(*,R_m,b_m,T_K,EOS='SW96',Pinternal_MPa,Pexternal_MPa,totaltime_s,steps,method='RK4',report_results='fullpath',plotfig=False,update_b=False, step_type='linear', max_perc_change=5):
464
497
  """
465
498
  Simulate the stretching of a CO2 fluid inclusion (FI) under constant external pressure (e.g., quenching or storage).
466
499
 
@@ -489,13 +522,23 @@ def stretch_at_constant_Pext(*,R_m,b_m,T_K,EOS='SW96',Pinternal_MPa,Pexternal_MP
489
522
  """
490
523
 
491
524
  CO2_dens_initial,CO2_mass_initial=get_initial_CO2(R_m=R_m,T_K=T_K,P_MPa=Pinternal_MPa,EOS=EOS)
525
+
526
+ # Check that you arent getting imaginary numbers.
527
+ dR_dt = calculate_dR_dt(R_m=R_m, b_m=b_m, Pinternal_MPa=Pinternal_MPa, Pexternal_MPa=Pexternal_MPa, T_K=T_K)
528
+
529
+ # Check if the result is complex
530
+ if isinstance(dR_dt, complex):
531
+ raise ValueError(f"The calculation returned a complex number due to invalid inputs. Most likely the inclusion radius, {1000000*R_m} (um), is too close, or even bigger than the defect distance, {1000000*b_m} um")
532
+
533
+
492
534
 
493
535
  results = pd.DataFrame([{'Time(s)': 0,
494
536
  'Step':0,
495
537
  'dt(s)':0,
496
538
  'Pexternal(MPa)': float(Pexternal_MPa),
497
539
  'Pinternal(MPa)': float(Pinternal_MPa),
498
- 'dR/dt(m/s)': float(calculate_dR_dt(R_m=R_m, b_m=b_m, Pinternal_MPa=Pinternal_MPa, Pexternal_MPa=Pexternal_MPa, T_K=T_K)),
540
+ 'deltaP (internal-external, MPa)':float(Pinternal_MPa)- float(Pexternal_MPa),
541
+ 'dR/dt(m/s)': float(calculate_dR_dt(R_m=R_m, b_m=b_m, Pinternal_MPa=Pinternal_MPa, Pexternal_MPa=Pexternal_MPa, T_K=T_K)), # ditched function due to issue with imaginary numbers
499
542
  'Fi_radius(μm)': float(R_m*10**6),
500
543
  'b (distance to xtal rim -μm)':float(b_m*10**6),
501
544
  '\u0394R/R0 (fractional change in radius)':0,
@@ -507,6 +550,7 @@ def stretch_at_constant_Pext(*,R_m,b_m,T_K,EOS='SW96',Pinternal_MPa,Pexternal_MP
507
550
  'dt(s)': 'float64',
508
551
  'Pexternal(MPa)': 'float64',
509
552
  'Pinternal(MPa)': 'float64',
553
+ 'deltaP (internal-external, MPa)': 'float64',
510
554
  'dR/dt(m/s)': 'float64',
511
555
  'Fi_radius(μm)': 'float64',
512
556
  'b (distance to xtal rim -μm)': 'float64',
@@ -515,24 +559,105 @@ def stretch_at_constant_Pext(*,R_m,b_m,T_K,EOS='SW96',Pinternal_MPa,Pexternal_MP
515
559
  })
516
560
 
517
561
 
518
- dt_s=totaltime_s/steps
519
-
520
- for step in range(1,steps):
562
+ if step_type== 'linear':
521
563
 
522
- R_new,dR_dt = get_R(R_m=R_m,b_m=b_m,T_K=T_K,Pinternal_MPa=Pinternal_MPa,Pexternal_MPa=Pexternal_MPa,dt_s=dt_s,method=method)
523
-
524
- CO2_dens_new,P_new = get_CO2dens_P(R_m=R_new,T_K=T_K,CO2_mass=CO2_mass_initial,EOS=EOS)
525
-
526
- Pinternal_MPa = P_new
527
- R_m=R_new
528
-
529
- if update_b==True:
530
- b_m=1000*R_m
564
+ dt_s=totaltime_s/steps
531
565
 
532
- results.loc[step] = [float(step * dt_s), int(step), float(dt_s), float(Pexternal_MPa), float(Pinternal_MPa),
533
- float(dR_dt), float(R_m * 10 ** 6), float(b_m * 10 ** 6),
534
- float((R_m * 10 ** 6 - results.loc[0, 'Fi_radius(μm)']) / results.loc[0, 'Fi_radius(μm)']),
535
- float(CO2_dens_new)]
566
+ for step in range(1,steps):
567
+
568
+ R_new,dR_dt = get_R(R_m=R_m,b_m=b_m,T_K=T_K,Pinternal_MPa=Pinternal_MPa,Pexternal_MPa=Pexternal_MPa,dt_s=dt_s,method=method)
569
+
570
+ CO2_dens_new,P_new = get_CO2dens_P(R_m=R_new,T_K=T_K,CO2_mass=CO2_mass_initial,EOS=EOS)
571
+
572
+ Pinternal_MPa = P_new
573
+ R_m=R_new
574
+
575
+ if update_b==True:
576
+ b_m=1000*R_m
577
+
578
+
579
+ results.loc[step] = [float(step * dt_s), int(step), float(dt_s), float(Pexternal_MPa), float(Pinternal_MPa), float(Pinternal_MPa-Pexternal_MPa),
580
+ float(dR_dt), float(R_m * 10 ** 6), float(b_m * 10 ** 6),
581
+ float((R_m * 10 ** 6 - results.loc[0, 'Fi_radius(μm)']) / results.loc[0, 'Fi_radius(μm)']),
582
+ float(CO2_dens_new)]
583
+
584
+ elif step_type == 'exponential':
585
+ total_time = 0
586
+ dt_s_array = calculate_exponential_time_steps(totaltime_s, steps)
587
+ local_step = 0 # Track position in the new dt_s_array
588
+
589
+ # Loop over steps
590
+ for step in range(steps): # Use global step index
591
+
592
+
593
+ if local_step >= len(dt_s_array): # Ensure no out-of-bounds access in the recalculated array
594
+ print(local_step)
595
+ print(dt_s_array)
596
+ print(f"Local step {local_step} exceeds the length of dt_s_array {len(dt_s_array)}, skipping.")
597
+ break # Avoid out-of-bounds access
598
+
599
+ dt_s = dt_s_array[local_step] # Use the local step to access dt_s_array
600
+ prev_Pinternal = Pinternal_MPa
601
+
602
+ # Accumulate the total time up to the current step
603
+ total_time += dt_s
604
+
605
+ # Update radius and pressure based on the current step
606
+ R_new, dR_dt = get_R(R_m=R_m, b_m=b_m, T_K=T_K, Pinternal_MPa=Pinternal_MPa, Pexternal_MPa=Pexternal_MPa, dt_s=dt_s, method=method)
607
+ CO2_dens_new, P_new = get_CO2dens_P(R_m=R_new, T_K=T_K, CO2_mass=CO2_mass_initial, EOS=EOS)
608
+
609
+ # Calculate the percentage change in internal pressure
610
+ perc_change = abs((P_new - prev_Pinternal) / prev_Pinternal) * 100
611
+
612
+
613
+ # Check if the pressure change exceeds the maximum allowed percentage change
614
+ while perc_change > max_perc_change:
615
+ print(f'Reducing step size, as pressure change was more than {max_perc_change}%.')
616
+
617
+ dt_s /= 2 # Reduce the step size
618
+ total_time -= dt_s # Remove the original dt_s from total_time
619
+ total_time += dt_s # Add the smaller dt_s
620
+
621
+ # Recalculate with the smaller dt_s
622
+ R_new, dR_dt = get_R(R_m=R_m, b_m=b_m, T_K=T_K, Pinternal_MPa=Pinternal_MPa, Pexternal_MPa=Pexternal_MPa, dt_s=dt_s, method=method)
623
+ CO2_dens_new, P_new = get_CO2dens_P(R_m=R_new, T_K=T_K, CO2_mass=CO2_mass_initial, EOS=EOS)
624
+
625
+ # Recalculate the percentage change
626
+ perc_change = abs((P_new - prev_Pinternal) / prev_Pinternal) * 100
627
+
628
+ # Recalculate dt_s_array to adjust future time steps based on the new dt_s
629
+ remaining_time = totaltime_s - total_time # Remaining time after this step
630
+ remaining_steps = steps - step # Remaining steps
631
+
632
+ if remaining_steps > 0:
633
+ dt_s_array = calculate_exponential_time_steps(remaining_time, remaining_steps)
634
+ local_step = 0 # Reset local step to start from the new dt_s_array's first value
635
+
636
+ # Increment local_step for the next iteration
637
+ local_step += 1
638
+
639
+
640
+ # Update the current internal pressure and radius
641
+ Pinternal_MPa = P_new
642
+ R_m = R_new
643
+
644
+ # Optionally update b_m if update_b is True
645
+ if update_b:
646
+ b_m = 1000 * R_m
647
+
648
+ # Store results for this step, using the accumulated total time
649
+ results.loc[step] = [float(total_time), # Accumulated total time
650
+ int(step), # Current step number
651
+ float(dt_s), # Time step for the current iteration
652
+ float(Pexternal_MPa),
653
+ float(Pinternal_MPa),
654
+ float(Pinternal_MPa-Pexternal_MPa),
655
+ float(dR_dt),
656
+ float(R_m * 10 ** 6),
657
+ float(b_m * 10 ** 6),
658
+ float((R_m * 10 ** 6 - results.loc[0, 'Fi_radius(μm)']) / results.loc[0, 'Fi_radius(μm)']),
659
+ float(CO2_dens_new)]
660
+
536
661
 
537
662
  if report_results == 'startendonly':
538
663
  results.drop(index=list(range(1, results.shape[0] - 1)), inplace=True) # Drop all rows except first and last
@@ -577,7 +702,7 @@ def stretch_at_constant_Pext(*,R_m,b_m,T_K,EOS='SW96',Pinternal_MPa,Pexternal_MP
577
702
  # This function can loop through different R and b value sets using stretch at constant Pext
578
703
 
579
704
  def loop_R_b_constant_Pext(*,R_m_values, b_m_values, T_K, EOS, Pinternal_MPa, Pexternal_MPa, totaltime_s, steps, T4endcalc_PD, method='RK4',
580
- plotfig=False, crustal_model_config=config_crustalmodel(crust_dens_kgm3=2750)):
705
+ plotfig=False, crustal_model_config=config_crustalmodel(crust_dens_kgm3=2750), step_type='linear', max_perc_change=5):
581
706
 
582
707
  """
583
708
  Perform multiple simulations under constant external pressure with various R and b values.
@@ -614,7 +739,7 @@ def loop_R_b_constant_Pext(*,R_m_values, b_m_values, T_K, EOS, Pinternal_MPa, Pe
614
739
  b_key = f'b{idx_b}' # Use 'b' followed by the index
615
740
  results = stretch_at_constant_Pext(R_m=R, b_m=b, T_K=T_K, Pinternal_MPa=Pinternal_MPa, Pexternal_MPa=Pexternal_MPa,
616
741
  totaltime_s=totaltime_s, steps=steps, EOS=EOS, method=method,
617
- plotfig=plotfig)
742
+ plotfig=plotfig, step_type=step_type, max_perc_change=max_perc_change)
618
743
  results['Calculated depths (km)_StorageT'] = convert_pressure_to_depth(
619
744
  P_kbar=results['Pinternal(MPa)'] / 100,
620
745
  crust_dens_kgm3=crustal_model_config.crust_dens_kgm3, g=9.81,
@@ -633,4 +758,4 @@ def loop_R_b_constant_Pext(*,R_m_values, b_m_values, T_K, EOS, Pinternal_MPa, Pe
633
758
 
634
759
  results_dict[R_key][b_key] = results
635
760
 
636
- return results_dict
761
+ return results_dict
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: DiadFit
3
- Version: 1.0.5
3
+ Version: 1.0.8
4
4
  Summary: DiadFit
5
5
  Home-page: https://github.com/PennyWieser/DiadFit
6
6
  Author: Penny Wieser
@@ -1,4 +1,4 @@
1
- DiadFit/CO2_EOS.py,sha256=H2_th8DP5m9oJ-IZCg9XncuOogQy_AE8ihiT-4zlIOo,74170
1
+ DiadFit/CO2_EOS.py,sha256=BFrmPxaMAdbLt_K0vTUnEyJZmyyWUyp_hVRScu9t7TI,74165
2
2
  DiadFit/CO2_in_bubble_error.py,sha256=Nq5YEf2oa2rWRreEPXl2lEA86NXOGvll0Gca2AOu_RE,21224
3
3
  DiadFit/H2O_fitting.py,sha256=XLNNgqmiIyj-ysRQeQFnk08Dlr6tFHFySY3Z-wEadxs,44914
4
4
  DiadFit/Highrho_polyfit_data.pkl,sha256=7t6uXxI-HdfsvreAWORzMa9dXxUsnXqKBSo1O3EgiBw,1213
@@ -29,21 +29,22 @@ DiadFit/Mediumrho_polyfit_data_CCMR.pkl,sha256=U6ODSdurqS0-lynm1MG1zktg8NuhYRbrY
29
29
  DiadFit/Mediumrho_polyfit_data_CMASS.pkl,sha256=SBy1pIdqCAF9UtB9FLNTuD0-tFyD7swwJppdE2U_FsY,1557
30
30
  DiadFit/Psensor.py,sha256=C2xSlgxhUJIKIBDvUp02QaYRs5QsIqjGGRMP25ZLRZ0,10435
31
31
  DiadFit/__init__.py,sha256=F-HjhCYKL_U8PfiH8tZ9DUCkxPvo6lAslJS4fyvxkbY,1148
32
- DiadFit/_version.py,sha256=599vLXXrjZtWlaxUrZujLY2-Ub1qzeOKj5Sk5VZAYKo,295
32
+ DiadFit/_version.py,sha256=nKWaPgClU1xtZYZ6_YcxZaeEJaW2vSv3ADjLG6ofSoo,295
33
33
  DiadFit/argon_lines.py,sha256=vtzsuDdEgrAmEF9xwpejpFqKV9hKPS1JUYhIl4AfXZ0,7675
34
34
  DiadFit/cosmicray_filter.py,sha256=a45x2_nmpi9Qcjc_L39UA9JOd1NMorIjtTRGnCdG3MU,23634
35
35
  DiadFit/densimeter_fitting.py,sha256=zEyCwq1zDV3z6-MIu-eZqgp3YQPUGqwZiKczN3-22LQ,8247
36
36
  DiadFit/densimeters.py,sha256=pSD8s9_9949bjWTbXU6SwoNgvsVBKGfQVf-JYMMtjrs,55282
37
- DiadFit/density_depth_crustal_profiles.py,sha256=b072IJaoGDydKpqWWKoJHeXKIkcIXxKf82whpvLAPpw,17761
38
- DiadFit/diads.py,sha256=ELG6wgEaGCYFj0IeA2F9QasYNmMVmFOi0rOl0oXv1pU,180906
39
- DiadFit/error_propagation.py,sha256=ipYI-Nwjv4f0sBdUiGeYV4wLcLGUXzKRrquNnc72d3c,50620
40
- DiadFit/importing_data_files.py,sha256=0Cx_CKJZR8efssMzQit0aPRh_rsjQFGXgLtI285FW_k,41961
37
+ DiadFit/density_depth_crustal_profiles.py,sha256=Vvtw3-_xuWIYEuhuDzXstkprluXyBkUcdm9iP7qBwyQ,19754
38
+ DiadFit/diads.py,sha256=lv6u9m71850_UnPqAOdFFeITMx5b0Dhn21i8tpDWj_Q,180939
39
+ DiadFit/error_propagation.py,sha256=ZN9EspONh_vUGxBHxxWNkYskKqFMRvJMNr2h2RXv-54,50624
40
+ DiadFit/importing_data_files.py,sha256=j7cSEPZ6iKmYnSqYEIcCl7YNdqqkCD56W-4V9T2oWOE,52010
41
41
  DiadFit/lookup_table.csv,sha256=Hs1tmSQ9ArTUDv3ymEXbvnLlPBxYUP0P51dz7xAKk-Q,2946857
42
42
  DiadFit/lookup_table_noneg.csv,sha256=HelvewKbBy4cqT2GAqsMo-1ps1lBYqZ-8hCJZWPGfhI,3330249
43
- DiadFit/molar_gas_proportions.py,sha256=_oEZn_vndHGDaXAjZ6UU8ycujBx_qB2KGCGqZSzotQU,3389
44
- DiadFit/ne_lines.py,sha256=in27yyvtlONf80KA2SREJ8xEemHvYTiWmd2-LOeJ7Tk,63955
45
- DiadFit/relaxifi.py,sha256=ZJ1LPWU1qKM8kU1ym4Ltp8skI_lMlhbCVhW6C1UhLb8,32109
46
- DiadFit-1.0.5.dist-info/METADATA,sha256=rz8zJHYmknOrLusf8A65vAdHe3-T3JeTriprj6FT4RI,1171
47
- DiadFit-1.0.5.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
48
- DiadFit-1.0.5.dist-info/top_level.txt,sha256=yZC6OFLVznaFA5kcPlFPkvhKotcVd-YO4bKxZZw3LQE,8
49
- DiadFit-1.0.5.dist-info/RECORD,,
43
+ DiadFit/molar_gas_proportions.py,sha256=mEcseIBFim5K7--9F0QwMT0QHin8Ubnm9U9iMSp7bI8,7337
44
+ DiadFit/ne_lines.py,sha256=KR1s33pZB_O8e3irtDLdBpepGwUjxWudjJNyHyXqfbg,63980
45
+ DiadFit/relaxfi_PW.py,sha256=vXXW9JjEBRf0UR9p-DJLx8j4Z2ePpUDweoAok-2nMJ0,32119
46
+ DiadFit/relaxifi.py,sha256=DSHAUP0tnkiMrHQgQPBK-9P3cWYmegURKzYOUgdAlos,38569
47
+ DiadFit-1.0.8.dist-info/METADATA,sha256=reLyXTzuAFqhm7f93wEwig0vQpWQxqgAK0w62Ehq3gQ,1171
48
+ DiadFit-1.0.8.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
49
+ DiadFit-1.0.8.dist-info/top_level.txt,sha256=yZC6OFLVznaFA5kcPlFPkvhKotcVd-YO4bKxZZw3LQE,8
50
+ DiadFit-1.0.8.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.44.0)
2
+ Generator: bdist_wheel (0.45.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5