freepaths 2.4.1__tar.gz → 2.4.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. {freepaths-2.4.1 → freepaths-2.4.2}/PKG-INFO +1 -1
  2. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/__main__.py +1 -1
  3. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/data.py +10 -0
  4. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/flight.py +31 -0
  5. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/output_plots.py +28 -3
  6. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/run_particle.py +1 -0
  7. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths.egg-info/PKG-INFO +1 -1
  8. {freepaths-2.4.1 → freepaths-2.4.2}/README.md +0 -0
  9. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/animation.py +0 -0
  10. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/config.py +0 -0
  11. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/default_config.py +0 -0
  12. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/electron.py +0 -0
  13. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/interface_smmm.py +0 -0
  14. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/main_mfp_sampling.py +0 -0
  15. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/main_tracing.py +0 -0
  16. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/maps.py +0 -0
  17. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/materials.py +0 -0
  18. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/move.py +0 -0
  19. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/options.py +0 -0
  20. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/output_electron_plots.py +0 -0
  21. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/output_info.py +0 -0
  22. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/output_structure.py +0 -0
  23. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/particle.py +0 -0
  24. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/phonon.py +0 -0
  25. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/post_computations.py +0 -0
  26. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/progress.py +0 -0
  27. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/scatterers.py +0 -0
  28. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/scattering.py +0 -0
  29. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/scattering_interfaces.py +0 -0
  30. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/scattering_primitives.py +0 -0
  31. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/scattering_semicircle.py +0 -0
  32. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/scattering_types.py +0 -0
  33. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/sources.py +0 -0
  34. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths.egg-info/SOURCES.txt +0 -0
  35. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths.egg-info/dependency_links.txt +0 -0
  36. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths.egg-info/entry_points.txt +0 -0
  37. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths.egg-info/requires.txt +0 -0
  38. {freepaths-2.4.1 → freepaths-2.4.2}/freepaths.egg-info/top_level.txt +0 -0
  39. {freepaths-2.4.1 → freepaths-2.4.2}/pyproject.toml +0 -0
  40. {freepaths-2.4.1 → freepaths-2.4.2}/setup.cfg +0 -0
  41. {freepaths-2.4.1 → freepaths-2.4.2}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: freepaths
3
- Version: 2.4.1
3
+ Version: 2.4.2
4
4
  Summary: Phonon Monte Carlo simulator
5
5
  Home-page: https://github.com/anufrievroman/freepaths
6
6
  Author: Roman Anufriev
@@ -7,7 +7,7 @@ from colorama import Fore, Style
7
7
 
8
8
  from freepaths.options import SimulationMode
9
9
 
10
- __version__ = "2.4.1"
10
+ __version__ = "2.4.2"
11
11
 
12
12
  colorama.init()
13
13
 
@@ -70,6 +70,10 @@ class GeneralData(Data):
70
70
  self.travel_times = []
71
71
  self.mean_free_paths = []
72
72
  self.thermal_conductivity = []
73
+ # Per-phonon internal and boundary scattering rates (MFP-sampling mode only),
74
+ # the two channels of the total rate v/MFP resolved as a function of frequency:
75
+ self.internal_scattering_rates = []
76
+ self.boundary_scattering_rates = []
73
77
  def save_particle_data(self, pt, mode=None):
74
78
  """Add information about the particle to the dataset"""
75
79
  from freepaths.options import SimulationMode
@@ -95,6 +99,8 @@ class GeneralData(Data):
95
99
  self.mean_free_paths.append(flight.mean_free_path)
96
100
  if mode is SimulationMode.PHONON_MFP_SAMPLING:
97
101
  self.thermal_conductivity.append(flight.thermal_conductivity)
102
+ self.internal_scattering_rates.append(flight.internal_scattering_rate)
103
+ self.boundary_scattering_rates.append(flight.boundary_scattering_rate)
98
104
 
99
105
  def write_into_files(self, mode=None):
100
106
  import os
@@ -121,6 +127,8 @@ class GeneralData(Data):
121
127
  np.savetxt("Data/All mean free paths.csv", self.mean_free_paths, fmt='%2.4e', header="MFPs [m]", encoding='utf-8')
122
128
  if mode is SimulationMode.PHONON_MFP_SAMPLING:
123
129
  np.savetxt("Data/All thermal conductivities.csv", self.thermal_conductivity, fmt='%2.4e', header="K [W/mK]", encoding='utf-8')
130
+ np.savetxt("Data/All internal scattering rates.csv", self.internal_scattering_rates, fmt='%2.4e', header="1/tau_internal [1/s]", encoding='utf-8')
131
+ np.savetxt("Data/All boundary scattering rates.csv", self.boundary_scattering_rates, fmt='%2.4e', header="1/tau_boundary [1/s]", encoding='utf-8')
124
132
  def dump_data(self):
125
133
  """Return data of a process in the form of a dictionary to be attached to the global data"""
126
134
  return {
@@ -136,6 +144,8 @@ class GeneralData(Data):
136
144
  'travel_times': self.travel_times,
137
145
  'mean_free_paths': self.mean_free_paths,
138
146
  'thermal_conductivity': self.thermal_conductivity,
147
+ 'internal_scattering_rates': self.internal_scattering_rates,
148
+ 'boundary_scattering_rates': self.boundary_scattering_rates,
139
149
  'initial_energies': self.initial_energies,
140
150
  }
141
151
 
@@ -45,6 +45,11 @@ class Flight:
45
45
  self.free_paths = []
46
46
  self._mfp_sum = 0.0
47
47
  self._mfp_count = 0
48
+ # Per-channel counts of the diffuse events that terminate a free-path segment,
49
+ # used to split the total scattering rate v/MFP into internal (phonon-phonon +
50
+ # impurity) and boundary (diffuse surface) spectra in the MFP-sampling mode:
51
+ self._internal_count = 0
52
+ self._boundary_count = 0
48
53
  self.hole_diff_scattering_angles = []
49
54
  self.hole_spec_scattering_angles = []
50
55
  self.thermal_conductivity = 0.0
@@ -53,6 +58,24 @@ class Flight:
53
58
  """Mean value of all free flights"""
54
59
  return self._mfp_sum / self._mfp_count if self._mfp_count else 0
55
60
 
61
+ @property
62
+ def internal_scattering_rate(self):
63
+ """Per-phonon internal (phonon-phonon + impurity) scattering rate [1/s]:
64
+ number of internal events divided by the total flight time (mfp_sum / speed).
65
+ Summed with boundary_scattering_rate this recovers the total rate v/MFP, so the
66
+ two split the total scattering-rate spectrum into physical channels."""
67
+ if self._mfp_sum <= 0:
68
+ return 0.0
69
+ return self.particle.speed * self._internal_count / self._mfp_sum
70
+
71
+ @property
72
+ def boundary_scattering_rate(self):
73
+ """Per-phonon boundary (diffuse surface) scattering rate [1/s]: number of
74
+ diffuse boundary events divided by the total flight time (mfp_sum / speed)."""
75
+ if self._mfp_sum <= 0:
76
+ return 0.0
77
+ return self.particle.speed * self._boundary_count / self._mfp_sum
78
+
56
79
  @property
57
80
  def mean_free_path_sem(self):
58
81
  """Standard error of the mean free path (MFP sampling mode only). Assumes
@@ -74,6 +97,14 @@ class Flight:
74
97
  if not cf.low_memory_usage:
75
98
  self.free_paths.append(self.free_path)
76
99
 
100
+ def record_scattering_channel(self, is_internal, is_boundary):
101
+ """Tally the channel of a diffuse event that ends a free-path segment, so the
102
+ total scattering rate can later be split into internal and boundary spectra."""
103
+ if is_internal:
104
+ self._internal_count += 1
105
+ if is_boundary:
106
+ self._boundary_count += 1
107
+
77
108
  def save_hole_diff_scattering_angle(self, angle):
78
109
  """Save angle of diffuse scattering from the hole"""
79
110
  self.hole_diff_scattering_angles.append(angle)
@@ -266,13 +266,24 @@ def plot_velocity_distribution():
266
266
 
267
267
 
268
268
  def plot_scattering_rate_vs_frequency():
269
- """Plot phonon scattering rate (1/τ = v/MFP) vs frequency with theoretical internal rate"""
269
+ """Plot phonon scattering rate (1/τ = v/MFP) vs frequency, resolved into the
270
+ internal (phonon-phonon + impurity) and boundary (diffuse surface) channels
271
+ measured in the simulation, with the theoretical internal rate overlaid."""
270
272
  mfps = np.loadtxt("Data/All mean free paths.csv")
271
273
  frequencies = np.loadtxt("Data/All final frequencies.csv")
272
274
  speeds = np.loadtxt("Data/All group velocities.csv")
273
275
  mask = mfps > 0
274
276
  scattering_rates = speeds[mask] / mfps[mask]
275
277
 
278
+ # Per-channel MC rates written by GeneralData in MFP-sampling mode (internal +
279
+ # boundary ≈ total). Optional so the plot still works on older result folders:
280
+ internal_rates = boundary_rates = None
281
+ try:
282
+ internal_rates = np.loadtxt("Data/All internal scattering rates.csv")
283
+ boundary_rates = np.loadtxt("Data/All boundary scattering rates.csv")
284
+ except OSError:
285
+ pass
286
+
276
287
  # Theoretical internal scattering rate from material model:
277
288
  material = get_media_class(cf.media)(cf.temp)
278
289
  f_range = np.linspace(frequencies[mask].min(), frequencies[mask].max(), 500)
@@ -281,9 +292,23 @@ def plot_scattering_rate_vs_frequency():
281
292
 
282
293
  step_rate_ns = 1e-9 / cf.timestep # 1/TIMESTEP in ns⁻¹
283
294
 
295
+ # Save the consolidated per-phonon spectra (frequency-sorted) to a single CSV so
296
+ # the Total/Internal/Boundary channels can be read without joining separate files:
297
+ if internal_rates is not None and boundary_rates is not None:
298
+ order = np.argsort(frequencies[mask])
299
+ spectra = np.column_stack((frequencies[mask], scattering_rates,
300
+ internal_rates[mask], boundary_rates[mask]))[order]
301
+ np.savetxt("Data/Distribution of scattering rates.csv", spectra,
302
+ fmt='%2.4e', delimiter=',',
303
+ header="f [Hz], Total (MC) [1/s], Internal (MC) [1/s], Boundary (MC) [1/s]",
304
+ encoding='utf-8')
305
+
284
306
  fig, ax = plt.subplots()
285
- ax.plot(frequencies[mask] * 1e-12, scattering_rates * 1e-9, '.', markersize=2, c='royalblue', label='MC total')
286
- ax.plot(f_range * 1e-12, 1e-9 / tau_internal, '--', linewidth=0.8, c='deeppink', label='Internal (theory)')
307
+ ax.plot(frequencies[mask] * 1e-12, scattering_rates * 1e-9, '.', markersize=2, c='black', label='Total (MC)')
308
+ if internal_rates is not None and boundary_rates is not None:
309
+ ax.plot(frequencies[mask] * 1e-12, internal_rates[mask] * 1e-9, '.', markersize=2, c='#5ec962', label='Internal (MC)')
310
+ ax.plot(frequencies[mask] * 1e-12, boundary_rates[mask] * 1e-9, '.', markersize=2, c='royalblue', label='Boundary (MC)')
311
+ ax.plot(f_range * 1e-12, 1e-9 / tau_internal, '--', linewidth=0.8, c='gray', label='Internal (Theory)')
287
312
  ax.set_xlabel('Frequency (THz)')
288
313
  ax.set_ylabel(r'Scattering rate (ns$^{-1}$)')
289
314
  ax.legend()
@@ -56,6 +56,7 @@ def run_particle(particle, flight, scatter_stats, places_stats, segment_stats, t
56
56
 
57
57
  # If diffuse scattering has occurred, reset particle free path:
58
58
  if scattering_types.is_diffuse or scattering_types.is_internal:
59
+ flight.record_scattering_channel(scattering_types.is_internal, scattering_types.is_diffuse)
59
60
  flight.save_free_paths()
60
61
  flight.restart()
61
62
  # An inelastic (anharmonic) internal event rethermalizes the phonon: new
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: freepaths
3
- Version: 2.4.1
3
+ Version: 2.4.2
4
4
  Summary: Phonon Monte Carlo simulator
5
5
  Home-page: https://github.com/anufrievroman/freepaths
6
6
  Author: Roman Anufriev
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes