sciforge_lib/physics/nuclear/
fusion.rs1use crate::constants::{C, EPSILON_0, G, K_B, MU_0, SIGMA_SB};
2
3pub fn pp_chain_rate(temperature_k: f64, density_kg_m3: f64, hydrogen_fraction: f64) -> f64 {
4 let t9 = temperature_k / 1e9;
5 if t9 <= 0.0 {
6 return 0.0;
7 }
8 let screening = 1.0 + 0.0123 * (density_kg_m3 / 1e5).powf(1.0 / 3.0) / t9;
9 let gamow = (-3.380 / t9.powf(1.0 / 3.0)).exp();
10 let s11 = 4.01e-22;
11 let rate = s11 * gamow * screening / t9.powf(2.0 / 3.0);
12 let energy_per_chain = 26.198 * 1.602_176_634e-13;
13 rate * density_kg_m3 * hydrogen_fraction.powi(2) * energy_per_chain
14}
15
16pub fn cno_cycle_rate(
17 temperature_k: f64,
18 density_kg_m3: f64,
19 hydrogen_fraction: f64,
20 cno_fraction: f64,
21) -> f64 {
22 let t9 = temperature_k / 1e9;
23 if t9 <= 0.0 {
24 return 0.0;
25 }
26 let gamow = (-15.228 / t9.powf(1.0 / 3.0)).exp();
27 let rate = 8.67e-17 * gamow / t9.powf(2.0 / 3.0);
28 let energy_per_cycle = 25.03 * 1.602_176_634e-13;
29 rate * density_kg_m3 * hydrogen_fraction * cno_fraction * energy_per_cycle
30}
31
32pub fn triple_alpha_rate(temperature_k: f64, density_kg_m3: f64, helium_fraction: f64) -> f64 {
33 let t9 = temperature_k / 1e9;
34 if t9 <= 0.0 {
35 return 0.0;
36 }
37 let rate = 7.831e-15 * (-4.4027 / t9).exp() / t9.powi(3);
38 let energy = 7.275 * 1.602_176_634e-13;
39 rate * density_kg_m3.powi(2) * helium_fraction.powi(3) * energy
40}
41
42pub fn nuclear_energy_generation(
43 temperature_k: f64,
44 density_kg_m3: f64,
45 hydrogen_fraction: f64,
46 helium_fraction: f64,
47 metal_fraction: f64,
48) -> f64 {
49 let pp = pp_chain_rate(temperature_k, density_kg_m3, hydrogen_fraction);
50 let cno = cno_cycle_rate(
51 temperature_k,
52 density_kg_m3,
53 hydrogen_fraction,
54 metal_fraction,
55 );
56 let ta = triple_alpha_rate(temperature_k, density_kg_m3, helium_fraction);
57 pp + cno + ta
58}
59
60pub fn thermal_pressure(electron_density: f64, temperature_k: f64) -> f64 {
61 2.0 * electron_density * K_B * temperature_k
62}
63
64pub fn magnetic_pressure(magnetic_field: f64) -> f64 {
65 magnetic_field.powi(2) / (2.0 * MU_0)
66}
67
68pub fn plasma_beta(electron_density: f64, temperature_k: f64, magnetic_field: f64) -> f64 {
69 thermal_pressure(electron_density, temperature_k) / magnetic_pressure(magnetic_field)
70}
71
72pub fn alfven_speed(magnetic_field: f64, density: f64) -> f64 {
73 magnetic_field / (MU_0 * density).sqrt()
74}
75
76pub fn plasma_frequency(electron_density: f64) -> f64 {
77 let e = 1.602_176_634e-19;
78 let m_e = 9.109_383_7e-31;
79 (electron_density * e * e / (EPSILON_0 * m_e)).sqrt()
80}
81
82pub fn debye_length(electron_density: f64, temperature_k: f64) -> f64 {
83 let e = 1.602_176_634e-19;
84 (EPSILON_0 * K_B * temperature_k / (electron_density * e * e)).sqrt()
85}
86
87pub fn radiative_loss_rate(electron_density: f64, temperature_k: f64) -> f64 {
88 let lambda = if temperature_k < 1e5 {
89 1e-26
90 } else if temperature_k < 1e7 {
91 1e-22 * (temperature_k / 1e6).powf(-0.7)
92 } else {
93 1e-23 * (temperature_k / 1e7).powf(0.5)
94 };
95 electron_density.powi(2) * lambda
96}
97
98pub fn thermal_conduction_flux(temperature_k: f64, length_scale: f64) -> f64 {
99 let kappa_0 = 9.2e-12;
100 kappa_0 * temperature_k.powf(3.5) / length_scale
101}
102
103pub fn sound_speed_plasma(temperature_k: f64, mean_particle_mass: f64) -> f64 {
104 let gamma = 5.0 / 3.0;
105 (gamma * K_B * temperature_k / mean_particle_mass).sqrt()
106}
107
108pub fn gyrofrequency(charge: f64, magnetic_field: f64, mass: f64) -> f64 {
109 charge.abs() * magnetic_field / mass
110}
111
112pub fn larmor_radius(mass: f64, velocity_perp: f64, charge: f64, magnetic_field: f64) -> f64 {
113 mass * velocity_perp / (charge.abs() * magnetic_field)
114}
115
116pub fn reconnection_rate_sweet_parker(alfven_speed_val: f64, lundquist_number: f64) -> f64 {
117 alfven_speed_val / lundquist_number.sqrt()
118}
119
120pub fn lundquist_number(
121 alfven_speed_val: f64,
122 length_scale: f64,
123 magnetic_diffusivity: f64,
124) -> f64 {
125 alfven_speed_val * length_scale / magnetic_diffusivity
126}
127
128pub fn coronal_loop_temperature(loop_length: f64, heating_rate: f64) -> f64 {
129 1400.0 * (heating_rate * loop_length.powi(2)).powf(1.0 / 3.0)
130}
131
132pub fn coronal_loop_density(heating_rate: f64, loop_length: f64, temperature_k: f64) -> f64 {
133 let kappa_0 = 9.2e-12;
134 heating_rate * loop_length / (2.0 * kappa_0 * temperature_k.powf(3.5) / loop_length) * 1e6
135}
136
137pub fn solar_flare_energy(magnetic_field: f64, volume: f64) -> f64 {
138 magnetic_pressure(magnetic_field) * volume
139}
140
141pub fn cme_kinetic_energy(mass: f64, velocity: f64) -> f64 {
142 0.5 * mass * velocity.powi(2)
143}
144
145pub fn sunspot_temperature(photosphere_temp: f64, suppression_factor: f64) -> f64 {
146 photosphere_temp * (1.0 - suppression_factor).powf(0.25)
147}
148
149pub fn differential_rotation_rate(equatorial_rate: f64, latitude: f64, a2: f64, a4: f64) -> f64 {
150 equatorial_rate - a2 * latitude.sin().powi(2) - a4 * latitude.sin().powi(4)
151}
152
153pub fn stellar_wind_mass_loss_si(luminosity: f64, escape_velocity: f64) -> f64 {
154 1e-14 * luminosity / (C * escape_velocity)
155}
156
157pub fn convective_envelope_depth(stellar_mass_solar: f64) -> f64 {
158 if stellar_mass_solar < 0.35 {
159 1.0
160 } else if stellar_mass_solar < 1.2 {
161 0.3 * (1.2 - stellar_mass_solar) / (1.2 - 0.35)
162 } else {
163 0.0
164 }
165}
166
167pub fn mixing_length_velocity(
168 convective_flux: f64,
169 density: f64,
170 temperature: f64,
171 pressure: f64,
172 mixing_length: f64,
173 g_local: f64,
174 cp: f64,
175) -> f64 {
176 let nabla_excess =
177 convective_flux / (density * cp * temperature * (pressure / (density * g_local)));
178 (g_local * mixing_length.powi(2) * nabla_excess / temperature).powf(1.0 / 3.0)
179}
180
181pub fn opacity_kramers(
182 density: f64,
183 temperature: f64,
184 hydrogen_fraction: f64,
185 metal_fraction: f64,
186) -> f64 {
187 let kappa_ff = 3.68e22
188 * (hydrogen_fraction + 0.2 * (1.0 + hydrogen_fraction))
189 * density
190 * temperature.powf(-3.5);
191 let kappa_bf =
192 4.34e25 * metal_fraction * (1.0 + hydrogen_fraction) * density * temperature.powf(-3.5);
193 kappa_ff + kappa_bf
194}
195
196pub fn radiative_temperature_gradient(
197 opacity: f64,
198 luminosity: f64,
199 mass_enclosed: f64,
200 pressure: f64,
201 temperature: f64,
202) -> f64 {
203 3.0 * opacity * luminosity * pressure
204 / (16.0 * std::f64::consts::PI * SIGMA_SB * C * G * mass_enclosed * temperature.powi(4))
205}