sciforge-hub 0.0.4

Central hub orchestrating Sciforge subsystems (api, engine, tools).
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
//! Dispatch handler for nuclear functions.

use super::super::params::*;
use crate::domain::common::errors::{HubError, HubResult};
use crate::domain::physics as phys;
use crate::engine::experience::runner::RunOutput;

fn make_process(p: &Params) -> HubResult<phys::nuclear::ProcessType> {
    let name = get_str(p, "process")?;
    match name {
        "pp_chain" => Ok(phys::nuclear::ProcessType::PPChain),
        "cno_cycle" => Ok(phys::nuclear::ProcessType::CNOCycle),
        "triple_alpha" => Ok(phys::nuclear::ProcessType::TripleAlpha),
        "carbon_burning" => Ok(phys::nuclear::ProcessType::CarbonBurning),
        "neon_burning" => Ok(phys::nuclear::ProcessType::NeonBurning),
        "oxygen_burning" => Ok(phys::nuclear::ProcessType::OxygenBurning),
        "silicon_burning" => Ok(phys::nuclear::ProcessType::SiliconBurning),
        "s_process" => Ok(phys::nuclear::ProcessType::SProcess),
        "r_process" => Ok(phys::nuclear::ProcessType::RProcess),
        "rp_process" => Ok(phys::nuclear::ProcessType::RPProcess),
        _ => Err(HubError::InvalidInput(format!(
            "unknown process type: {name}"
        ))),
    }
}

pub(super) fn dispatch(func: &str, p: &Params) -> HubResult<RunOutput> {
    match func {
        "activity_becquerel" => Ok(RunOutput::Scalar(
            phys::nuclear::activity_becquerel(get_f(p, "n_atoms")?, get_f(p, "half_life")?),
        )),
        "activity_curie" => Ok(RunOutput::Scalar(phys::nuclear::activity_curie(
            get_f(p, "n_atoms")?,
            get_f(p, "half_life")?,
        ))),
        "alpha_decay_q" => Ok(RunOutput::Scalar(phys::nuclear::alpha_decay_q(
            get_f(p, "parent_mass_mev")?,
            get_f(p, "daughter_mass_mev")?,
            get_f(p, "alpha_mass_mev")?,
        ))),
        "astrophysical_s_factor" => Ok(RunOutput::Scalar(
            phys::nuclear::astrophysical_s_factor(
                get_f(p, "cross_section_barn")?,
                get_f(p, "energy_kev")?,
                get_i(p, "z1")? as u32,
                get_i(p, "z2")? as u32,
                get_f(p, "mu_amu")?,
            ),
        )),
        "bateman_chain" => Ok(RunOutput::Vector(phys::nuclear::bateman_chain(
            get_f(p, "n0")?,
            get_v(p, "lambdas")?,
            get_f(p, "time")?,
        ))),
        "beta_minus_q" => Ok(RunOutput::Scalar(phys::nuclear::beta_minus_q(
            get_f(p, "parent_mass_amu")?,
            get_f(p, "daughter_mass_amu")?,
        ))),
        "beta_plus_q" => Ok(RunOutput::Scalar(phys::nuclear::beta_plus_q(
            get_f(p, "parent_mass_amu")?,
            get_f(p, "daughter_mass_amu")?,
        ))),
        "binding_energy_per_nucleon_semf" => Ok(RunOutput::Scalar(
            phys::nuclear::binding_energy_per_nucleon_semf(
                get_i(p, "z")? as u32,
                get_i(p, "a")? as u32,
            ),
        )),
        "branching_ratio_effective" => Ok(RunOutput::Vector(
            phys::nuclear::branching_ratio_effective(get_v(p, "partial_constants")?),
        )),
        "c12_alpha_rate_estimate" => Ok(RunOutput::Scalar(
            phys::nuclear::c12_alpha_rate_estimate(get_f(p, "temperature_k")?),
        )),
        "cno_cycle_is_dominant" => Ok(RunOutput::Boolean(
            phys::nuclear::cno_cycle_is_dominant(
                get_f(p, "temperature_k")?,
                get_f(p, "metallicity")?,
            ),
        )),
        "core_collapse_min_mass_solar" => Ok(RunOutput::Scalar(
            phys::nuclear::core_collapse_min_mass_solar(),
        )),
        "coulomb_barrier" => Ok(RunOutput::Scalar(phys::nuclear::coulomb_barrier(
            get_i(p, "z1")? as u32,
            get_i(p, "z2")? as u32,
            get_i(p, "a1")? as u32,
            get_i(p, "a2")? as u32,
        ))),
        "decay_chain_equilibrium_time" => Ok(RunOutput::Scalar(
            phys::nuclear::decay_chain_equilibrium_time(
                get_f(p, "lambda_parent")?,
                get_f(p, "lambda_daughter")?,
            ),
        )),
        "decay_constant_from_half_life" => Ok(RunOutput::Scalar(
            phys::nuclear::decay_constant_from_half_life(get_f(p, "half_life")?),
        )),
        "decay_remaining" => Ok(RunOutput::Scalar(phys::nuclear::decay_remaining(
            get_f(p, "n0")?,
            get_f(p, "half_life")?,
            get_f(p, "time")?,
        ))),
        "dose_rate_point_source" => Ok(RunOutput::Scalar(
            phys::nuclear::dose_rate_point_source(
                get_f(p, "activity_bq")?,
                get_f(p, "gamma_constant")?,
                get_f(p, "distance_m")?,
            ),
        )),
        "eddington_luminosity_solar" => Ok(RunOutput::Scalar(
            phys::nuclear::eddington_luminosity_solar(get_f(p, "mass_solar")?),
        )),
        "electron_degeneracy_pressure" => Ok(RunOutput::Scalar(
            phys::nuclear::electron_degeneracy_pressure(get_f(p, "density_kg_m3")?),
        )),
        "fission_barrier_estimate_mev" => Ok(RunOutput::Scalar(
            phys::nuclear::fission_barrier_estimate_mev(
                get_i(p, "z")? as u32,
                get_i(p, "a")? as u32,
            ),
        )),
        "gamow_peak" => Ok(RunOutput::Scalar(phys::nuclear::gamow_peak(
            get_i(p, "z1")? as u32,
            get_i(p, "z2")? as u32,
            get_f(p, "reduced_mass_amu")?,
            get_f(p, "temperature_k")?,
        ))),
        "gamow_window_width" => Ok(RunOutput::Scalar(
            phys::nuclear::gamow_window_width(
                get_i(p, "z1")? as u32,
                get_i(p, "z2")? as u32,
                get_f(p, "reduced_mass_amu")?,
                get_f(p, "temperature_k")?,
            ),
        )),
        "geiger_nuttall" => Ok(RunOutput::Scalar(phys::nuclear::geiger_nuttall(
            get_i(p, "z")? as u32,
            get_f(p, "energy_mev")?,
        ))),
        "half_life_from_constant" => Ok(RunOutput::Scalar(
            phys::nuclear::half_life_from_constant(get_f(p, "decay_constant")?),
        )),
        "iron_peak_binding_energy" => Ok(RunOutput::Scalar(
            phys::nuclear::iron_peak_binding_energy(),
        )),
        "is_doubly_magic" => Ok(RunOutput::Boolean(phys::nuclear::is_doubly_magic(
            get_i(p, "z")? as u32,
            get_i(p, "n")? as u32,
        ))),
        "isospin_z" => Ok(RunOutput::Scalar(phys::nuclear::isospin_z(
            get_i(p, "z")? as u32,
            get_i(p, "a")? as u32,
        ))),
        "jeans_mass_solar" => Ok(RunOutput::Scalar(phys::nuclear::jeans_mass_solar(
            get_f(p, "temperature_k")?,
            get_f(p, "density_kg_m3")?,
        ))),
        "kelvin_helmholtz_timescale_years" => Ok(RunOutput::Scalar(
            phys::nuclear::kelvin_helmholtz_timescale_years(
                get_f(p, "mass_solar")?,
                get_f(p, "radius_solar")?,
                get_f(p, "luminosity_solar")?,
            ),
        )),
        "liquid_drop_fission_parameter" => Ok(RunOutput::Scalar(
            phys::nuclear::liquid_drop_fission_parameter(
                get_i(p, "z")? as u32,
                get_i(p, "a")? as u32,
            ),
        )),
        "luminosity_radius_temperature" => Ok(RunOutput::Scalar(
            phys::nuclear::luminosity_radius_temperature(
                get_f(p, "radius_solar")?,
                get_f(p, "temperature_k")?,
            ),
        )),
        "magic_number_nearest" => Ok(RunOutput::Scalar(
            phys::nuclear::magic_number_nearest(get_i(p, "n")? as u32) as f64,
        )),
        "maxwell_averaged_velocity" => Ok(RunOutput::Scalar(
            phys::nuclear::maxwell_averaged_velocity(
                get_f(p, "temperature_k")?,
                get_f(p, "mu_amu")?,
            ),
        )),
        "mean_lifetime" => Ok(RunOutput::Scalar(phys::nuclear::mean_lifetime(
            get_f(p, "half_life")?,
        ))),
        "neutron_capture_rate_estimate" => Ok(RunOutput::Scalar(
            phys::nuclear::neutron_capture_rate_estimate(
                get_f(p, "neutron_density_per_cm3")?,
                get_f(p, "cross_section_barn")?,
                get_f(p, "velocity_cm_s")?,
            ),
        )),
        "neutron_drip_density" => Ok(RunOutput::Scalar(
            phys::nuclear::neutron_drip_density(),
        )),
        "neutron_drip_line_a" => Ok(RunOutput::Scalar(
            phys::nuclear::neutron_drip_line_a(get_i(p, "z")? as u32) as f64,
        )),
        "neutron_excess" => Ok(RunOutput::Scalar(phys::nuclear::neutron_excess(
            get_i(p, "z")? as u32,
            get_i(p, "a")? as u32,
        ) as f64)),
        "neutron_star_radius_km" => Ok(RunOutput::Scalar(
            phys::nuclear::neutron_star_radius_km(get_f(p, "mass_solar")?),
        )),
        "nuclear_density_kg_m3" => Ok(RunOutput::Scalar(
            phys::nuclear::nuclear_density_kg_m3(),
        )),
        "nuclear_radius_fm" => Ok(RunOutput::Scalar(phys::nuclear::nuclear_radius_fm(
            get_i(p, "a")? as u32,
        ))),
        "nuclear_reaction_lifetime" => Ok(RunOutput::Scalar(
            phys::nuclear::nuclear_reaction_lifetime(
                get_f(p, "cross_section_barn")?,
                get_f(p, "number_density_per_cm3")?,
                get_f(p, "velocity_cm_s")?,
            ),
        )),
        "nuclear_skin_thickness_fm" => Ok(RunOutput::Scalar(
            phys::nuclear::nuclear_skin_thickness_fm(
                get_i(p, "z")? as u32,
                get_i(p, "a")? as u32,
            ),
        )),
        "nuclear_statistical_equilibrium_temp" => Ok(RunOutput::Scalar(
            phys::nuclear::nuclear_statistical_equilibrium_temp(),
        )),
        "nuclear_timescale_years" => Ok(RunOutput::Scalar(
            phys::nuclear::nuclear_timescale_years(
                get_f(p, "mass_solar")?,
                get_f(p, "luminosity_solar")?,
                get_f(p, "efficiency")?,
            ),
        )),
        "penetration_factor" => Ok(RunOutput::Scalar(
            phys::nuclear::penetration_factor(
                get_i(p, "z1")? as u32,
                get_i(p, "z2")? as u32,
                get_f(p, "energy_kev")?,
                get_f(p, "mu_amu")?,
            ),
        )),
        "pp_chain_branches" => {
            let r = phys::nuclear::pp_chain_branches(get_f(p, "temperature_k")?);
            Ok(RunOutput::Triple(r.0, r.1, r.2))
        }
        "pp_rate_estimate" => Ok(RunOutput::Scalar(phys::nuclear::pp_rate_estimate(
            get_f(p, "temperature_k")?,
            get_f(p, "density_g_cm3")?,
            get_f(p, "x_h")?,
        ))),
        "proton_drip_line_a" => Ok(RunOutput::Scalar(
            phys::nuclear::proton_drip_line_a(get_i(p, "z")? as u32) as f64,
        )),
        "r_process_waiting_point_z" => Ok(RunOutput::Scalar(
            phys::nuclear::r_process_waiting_point_z(
                get_f(p, "neutron_separation_energy_mev")?,
                get_f(p, "temperature_gk")?,
            ),
        )),
        "radioactive_dating_age" => Ok(RunOutput::Scalar(
            phys::nuclear::radioactive_dating_age(
                get_f(p, "ratio_daughter_parent")?,
                get_f(p, "half_life")?,
            ),
        )),
        "reaction_mean_free_path" => Ok(RunOutput::Scalar(
            phys::nuclear::reaction_mean_free_path(
                get_f(p, "cross_section_barn")?,
                get_f(p, "number_density_per_cm3")?,
            ),
        )),
        "reduced_mass_amu" => Ok(RunOutput::Scalar(phys::nuclear::reduced_mass_amu(
            get_f(p, "m1")?,
            get_f(p, "m2")?,
        ))),
        "s_process_neutron_exposure" => Ok(RunOutput::Scalar(
            phys::nuclear::s_process_neutron_exposure(
                get_f(p, "tau")?,
                get_f(p, "sigma_times_flux")?,
            ),
        )),
        "schwarzschild_radius_km" => Ok(RunOutput::Scalar(
            phys::nuclear::schwarzschild_radius_km(get_f(p, "mass_solar")?),
        )),
        "secular_equilibrium_activity" => Ok(RunOutput::Scalar(
            phys::nuclear::secular_equilibrium_activity(get_f(p, "parent_activity")?),
        )),
        "semi_empirical_mass" => Ok(RunOutput::Scalar(
            phys::nuclear::semi_empirical_mass(
                get_i(p, "z")? as u32,
                get_i(p, "a")? as u32,
            ),
        )),
        "separation_energy_alpha" => Ok(RunOutput::Scalar(
            phys::nuclear::separation_energy_alpha(
                get_i(p, "z")? as u32,
                get_i(p, "a")? as u32,
            ),
        )),
        "separation_energy_neutron" => Ok(RunOutput::Scalar(
            phys::nuclear::separation_energy_neutron(
                get_i(p, "z")? as u32,
                get_i(p, "a")? as u32,
            ),
        )),
        "separation_energy_proton" => Ok(RunOutput::Scalar(
            phys::nuclear::separation_energy_proton(
                get_i(p, "z")? as u32,
                get_i(p, "a")? as u32,
            ),
        )),
        "sommerfeld_parameter" => Ok(RunOutput::Scalar(
            phys::nuclear::sommerfeld_parameter(
                get_i(p, "z1")? as u32,
                get_i(p, "z2")? as u32,
                get_f(p, "energy_kev")?,
                get_f(p, "mu_amu")?,
            ),
        )),
        "specific_activity" => Ok(RunOutput::Scalar(phys::nuclear::specific_activity(
            get_f(p, "decay_constant")?,
            get_f(p, "molar_mass")?,
        ))),
        "stellar_wind_mass_loss" => Ok(RunOutput::Scalar(
            phys::nuclear::stellar_wind_mass_loss(
                get_f(p, "luminosity_solar")?,
                get_f(p, "escape_velocity_km_s")?,
            ),
        )),
        "thermonuclear_rate" => Ok(RunOutput::Scalar(
            phys::nuclear::thermonuclear_rate(
                get_f(p, "s_factor_kev_barn")?,
                get_i(p, "z1")? as u32,
                get_i(p, "z2")? as u32,
                get_f(p, "mu_amu")?,
                get_f(p, "temperature_k")?,
            ),
        )),
        "tolman_oppenheimer_volkoff_limit" => Ok(RunOutput::Scalar(
            phys::nuclear::tolman_oppenheimer_volkoff_limit(),
        )),
        "transient_equilibrium_ratio" => Ok(RunOutput::Scalar(
            phys::nuclear::transient_equilibrium_ratio(
                get_f(p, "lambda_parent")?,
                get_f(p, "lambda_daughter")?,
            ),
        )),
        "triple_alpha_rate_estimate" => Ok(RunOutput::Scalar(
            phys::nuclear::triple_alpha_rate_estimate(
                get_f(p, "temperature_k")?,
                get_f(p, "density_g_cm3")?,
                get_f(p, "y_he")?,
            ),
        )),
        "valley_of_stability_z" => Ok(RunOutput::Scalar(
            phys::nuclear::valley_of_stability_z(get_i(p, "a")? as u32),
        )),
        "weizsacker_mass_excess_mev" => Ok(RunOutput::Scalar(
            phys::nuclear::weizsacker_mass_excess_mev(
                get_i(p, "z")? as u32,
                get_i(p, "a")? as u32,
            ),
        )),
        "white_dwarf_radius_km" => Ok(RunOutput::Scalar(
            phys::nuclear::white_dwarf_radius_km(get_f(p, "mass_solar")?),
        )),
        "active_processes" => {
            let r = phys::nuclear::active_processes(get_f(p, "temperature_k")?);
            Ok(RunOutput::Text(
                r.iter()
                    .map(|pt: &phys::nuclear::ProcessType| pt.to_string())
                    .collect::<Vec<_>>()
                    .join(", "),
            ))
        }
        "chandrasekhar_limit" => Ok(RunOutput::Scalar(
            phys::nuclear::chandrasekhar_limit(),
        )),
        "dominant_process_at" => {
            let r = phys::nuclear::dominant_process_at(get_f(p, "temperature_k")?);
            Ok(RunOutput::Text(
                r.map_or_else(|| "none".to_string(), |pt: phys::nuclear::ProcessType| pt.to_string()),
            ))
        }
        "process_fuel" => {
            let pt = make_process(p)?;
            Ok(RunOutput::Text(
                phys::nuclear::process_fuel(&pt).to_string(),
            ))
        }
        "process_product" => {
            let pt = make_process(p)?;
            Ok(RunOutput::Text(
                phys::nuclear::process_product(&pt).to_string(),
            ))
        }
        "process_timescale_years" => {
            let pt = make_process(p)?;
            Ok(RunOutput::Scalar(
                phys::nuclear::process_timescale_years(&pt, get_f(p, "mass_solar")?),
            ))
        }
        "cross_section_barn_to_si" => Ok(RunOutput::Scalar(
            phys::nuclear::cross_section_barn_to_si(get_f(p, "sigma_barn")?),
        )),
        "nuclear_radius_fermi" => Ok(RunOutput::Scalar(
            phys::nuclear::nuclear_radius_fermi(get_i(p, "a")? as u32),
        )),
        "nuclear_volume" => Ok(RunOutput::Scalar(phys::nuclear::nuclear_volume(
            get_i(p, "a")? as u32,
        ))),
        "q_value_to_joules" => Ok(RunOutput::Scalar(phys::nuclear::q_value_to_joules(
            get_f(p, "q_mev")?,
        ))),
        "geometric_cross_section" => Ok(RunOutput::Scalar(
            phys::nuclear::geometric_cross_section(
                get_i(p, "a1")? as u32,
                get_i(p, "a2")? as u32,
            ),
        )),
        "geometric_cross_section_barn" => Ok(RunOutput::Scalar(
            phys::nuclear::geometric_cross_section_barn(
                get_i(p, "a1")? as u32,
                get_i(p, "a2")? as u32,
            ),
        )),
        _ => Err(HubError::InvalidInput(format!("unknown function: {func}"))),
    }
}