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.
- {freepaths-2.4.1 → freepaths-2.4.2}/PKG-INFO +1 -1
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/__main__.py +1 -1
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/data.py +10 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/flight.py +31 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/output_plots.py +28 -3
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/run_particle.py +1 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths.egg-info/PKG-INFO +1 -1
- {freepaths-2.4.1 → freepaths-2.4.2}/README.md +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/animation.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/config.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/default_config.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/electron.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/interface_smmm.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/main_mfp_sampling.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/main_tracing.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/maps.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/materials.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/move.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/options.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/output_electron_plots.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/output_info.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/output_structure.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/particle.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/phonon.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/post_computations.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/progress.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/scatterers.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/scattering.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/scattering_interfaces.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/scattering_primitives.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/scattering_semicircle.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/scattering_types.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths/sources.py +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths.egg-info/SOURCES.txt +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths.egg-info/dependency_links.txt +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths.egg-info/entry_points.txt +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths.egg-info/requires.txt +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/freepaths.egg-info/top_level.txt +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/pyproject.toml +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/setup.cfg +0 -0
- {freepaths-2.4.1 → freepaths-2.4.2}/setup.py +0 -0
|
@@ -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
|
|
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='
|
|
286
|
-
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|