use xraydb::XrayDb;
#[cfg(feature = "optics")]
mod optics {
use super::*;
use xraydb::{CoatedMirrorParams, DarwinParams, MirrorParams, MultilayerParams, Polarization};
#[test]
fn test_darwin_width_si_111() {
let db = XrayDb::new();
let dw = db
.darwin_width(DarwinParams {
energy: 10000.0,
crystal: "Si",
hkl: (1, 1, 1),
lattice_constant: None,
polarization: Polarization::S,
ignore_f1: false,
ignore_f2: false,
order: 1,
})
.unwrap();
let dw = dw.expect("Bragg condition should be satisfied at 10 keV");
let theta_deg = dw.theta.to_degrees();
assert!(
theta_deg > 10.0 && theta_deg < 13.0,
"theta = {theta_deg} deg"
);
assert!(dw.energy_width > 0.1, "energy_width = {}", dw.energy_width);
assert!(
dw.energy_width < 100.0,
"energy_width = {}",
dw.energy_width
);
assert!(dw.theta_width > 0.0);
assert!(dw.theta_fwhm > 0.0);
let max_intensity = dw.intensity.iter().cloned().fold(0.0_f64, f64::max);
assert!(max_intensity > 0.8, "max intensity = {max_intensity}");
assert!(dw.rocking_energy_fwhm > 0.0);
}
#[test]
fn test_darwin_width_si_220() {
let db = XrayDb::new();
let dw = db
.darwin_width(DarwinParams {
energy: 10000.0,
crystal: "Si",
hkl: (2, 2, 0),
lattice_constant: None,
polarization: Polarization::S,
ignore_f1: false,
ignore_f2: false,
order: 1,
})
.unwrap();
let dw = dw.expect("Bragg condition should be satisfied");
let dw_111 = db
.darwin_width(DarwinParams {
energy: 10000.0,
crystal: "Si",
hkl: (1, 1, 1),
lattice_constant: None,
polarization: Polarization::S,
ignore_f1: false,
ignore_f2: false,
order: 1,
})
.unwrap()
.unwrap();
assert!(dw.theta > dw_111.theta);
assert!(dw.energy_width < dw_111.energy_width);
}
#[test]
fn test_darwin_width_bragg_impossible() {
let db = XrayDb::new();
let result = db
.darwin_width(DarwinParams {
energy: 100.0,
crystal: "Si",
hkl: (1, 1, 1),
lattice_constant: None,
polarization: Polarization::S,
ignore_f1: false,
ignore_f2: false,
order: 1,
})
.unwrap();
assert!(result.is_none());
}
#[test]
fn test_darwin_width_p_polarization() {
let db = XrayDb::new();
let dw_s = db
.darwin_width(DarwinParams {
energy: 10000.0,
crystal: "Si",
hkl: (1, 1, 1),
lattice_constant: None,
polarization: Polarization::S,
ignore_f1: false,
ignore_f2: false,
order: 1,
})
.unwrap()
.unwrap();
let dw_p = db
.darwin_width(DarwinParams {
energy: 10000.0,
crystal: "Si",
hkl: (1, 1, 1),
lattice_constant: None,
polarization: Polarization::P,
ignore_f1: false,
ignore_f2: false,
order: 1,
})
.unwrap()
.unwrap();
assert!(dw_p.energy_width < dw_s.energy_width);
}
#[test]
fn test_darwin_width_ge() {
let db = XrayDb::new();
let dw = db
.darwin_width(DarwinParams {
energy: 10000.0,
crystal: "Ge",
hkl: (1, 1, 1),
lattice_constant: None,
polarization: Polarization::S,
ignore_f1: false,
ignore_f2: false,
order: 1,
})
.unwrap();
assert!(dw.is_some());
}
#[test]
fn test_mirror_reflectivity_si() {
let db = XrayDb::new();
let theta: Vec<f64> = (1..100)
.map(|i| i as f64 * 0.1e-3) .collect();
let refl = db
.mirror_reflectivity(MirrorParams {
formula: "Si",
theta: &theta,
energy: 10000.0,
density: 2.33,
roughness: 0.0,
polarization: Polarization::S,
})
.unwrap();
assert_eq!(refl.len(), theta.len());
assert!(refl[0] > 0.9, "R at 0.1 mrad = {}", refl[0]);
let last = refl.len() - 1;
assert!(refl[last] < 0.1, "R at 10 mrad = {}", refl[last]);
}
#[test]
fn test_mirror_reflectivity_pt() {
let db = XrayDb::new();
let theta: Vec<f64> = (1..50).map(|i| i as f64 * 0.5e-3).collect();
let refl = db
.mirror_reflectivity(MirrorParams {
formula: "Pt",
theta: &theta,
energy: 10000.0,
density: 21.45,
roughness: 0.0,
polarization: Polarization::S,
})
.unwrap();
let refl_si = db
.mirror_reflectivity(MirrorParams {
formula: "Si",
theta: &theta,
energy: 10000.0,
density: 2.33,
roughness: 0.0,
polarization: Polarization::S,
})
.unwrap();
let mid = theta.len() / 2;
assert!(
refl[mid] > refl_si[mid],
"Pt R = {}, Si R = {} at theta = {}",
refl[mid],
refl_si[mid],
theta[mid]
);
}
#[test]
fn test_mirror_reflectivity_roughness() {
let db = XrayDb::new();
let theta: Vec<f64> = (1..50).map(|i| i as f64 * 0.2e-3).collect();
let smooth = db
.mirror_reflectivity(MirrorParams {
formula: "Si",
theta: &theta,
energy: 10000.0,
density: 2.33,
roughness: 0.0,
polarization: Polarization::S,
})
.unwrap();
let rough = db
.mirror_reflectivity(MirrorParams {
formula: "Si",
theta: &theta,
energy: 10000.0,
density: 2.33,
roughness: 5.0,
polarization: Polarization::S,
})
.unwrap();
for i in 0..smooth.len() {
assert!(
rough[i] <= smooth[i] + 1e-10,
"rough > smooth at i={}: {} vs {}",
i,
rough[i],
smooth[i]
);
}
}
#[test]
fn test_multilayer_si_w() {
let db = XrayDb::new();
let theta: Vec<f64> = (1..100).map(|i| i as f64 * 0.1e-3).collect();
let refl = db
.multilayer_reflectivity(MultilayerParams {
stackup: &["W", "Si"],
thickness: &[20.0, 20.0],
density: &[19.25, 2.33],
substrate: "Si",
substrate_density: 2.33,
theta: &theta,
energy: 10000.0,
n_periods: 20,
substrate_roughness: 0.0,
surface_roughness: 0.0,
polarization: Polarization::S,
})
.unwrap();
assert_eq!(refl.len(), theta.len());
let max_refl = refl.iter().cloned().fold(0.0_f64, f64::max);
assert!(max_refl > 0.01, "max multilayer reflectivity = {max_refl}");
}
#[test]
fn test_coated_reflectivity_rh() {
let db = XrayDb::new();
let theta: Vec<f64> = (1..50).map(|i| i as f64 * 0.2e-3).collect();
let refl = db
.coated_reflectivity(CoatedMirrorParams {
coating: "Rh",
coating_thickness: 500.0,
coating_density: 12.41,
substrate: "Si",
substrate_density: 2.33,
theta: &theta,
energy: 10000.0,
..Default::default()
})
.unwrap();
assert_eq!(refl.len(), theta.len());
assert!(refl[0] > 0.5, "R at small angle = {}", refl[0]);
}
}
#[test]
fn test_find_material() {
let db = XrayDb::new();
let water = db.find_material("water").unwrap();
assert_eq!(water.formula, "H2O");
assert!((water.density - 1.0).abs() < 1e-6);
let silicon = db.find_material("silicon").unwrap();
assert_eq!(silicon.formula, "Si");
assert!((silicon.density - 2.329).abs() < 0.01);
let kapton = db.find_material("kapton").unwrap();
assert_eq!(kapton.formula, "C22H10N2O5");
assert!((kapton.density - 1.42).abs() < 0.01);
assert!(db.find_material("Water").is_some());
assert!(db.find_material("SILICON").is_some());
assert!(db.find_material("unobtainium").is_none());
}
#[test]
fn test_material_mu_named() {
let db = XrayDb::new();
let mu = db
.material_mu_named("water", &[10000.0], xraydb::CrossSectionKind::Total, None)
.unwrap();
assert!(mu[0] > 0.0);
assert!(mu[0] < 100.0);
}
#[test]
fn test_ionchamber_nitrogen() {
let db = XrayDb::new();
let fluxes = db
.ionchamber_fluxes(
&[("nitrogen", 1.0)],
1.0, 100.0, 10000.0,
1e-6, true,
true,
)
.unwrap();
assert!(fluxes.incident > 0.0, "incident = {}", fluxes.incident);
assert!(fluxes.transmitted < fluxes.incident);
assert!(fluxes.photo > 0.0);
}
#[test]
fn test_ionchamber_argon() {
let db = XrayDb::new();
let fluxes = db
.ionchamber_fluxes(
&[("argon", 1.0)],
1.0,
30.0, 10000.0,
1e-6,
true,
true,
)
.unwrap();
assert!(fluxes.incident > 0.0);
let fluxes_n = db
.ionchamber_fluxes(&[("nitrogen", 1.0)], 1.0, 30.0, 10000.0, 1e-6, true, true)
.unwrap();
assert!(
fluxes.incident < fluxes_n.incident,
"Ar incident = {}, N2 incident = {}",
fluxes.incident,
fluxes_n.incident
);
}