From 74cc36d878de94af0f0322791ce24a152a2ede68 Mon Sep 17 00:00:00 2001 From: Peter Willendrup Date: Fri, 30 Oct 2026 07:52:29 +0100 Subject: [PATCH 1/2] McXtrace Single_crystal: absorption from mu/rho times mass density The absorption cross-section was the per-atom value (atomic weight from e.g. Si.txt A[r]) divided by the full unit cell volume, so multi-atom cells absorbed too little: Si.lau (8 atoms/cell) gave an attenuation length of 360 um at 6.9 keV instead of 45 um. Use the textbook linear attenuation mu/rho [cm^2/g] * density [g/cm^3], with the density from the reflections file header, else the nominal density of the material_datafile. Keep the old expression only as a fallback when no density is known. Numerical change: unchanged for cif2hkl output where weight is per formula unit (LaB6 Test_PowderN/Test_FluoPowder identical); stronger absorption for Si.lau (SSRL_bl_11_2_*, Test_Mono Mono=6). Co-Authored-By: Claude Opus 5.5 --- mcxtrace-comps/samples/Single_crystal.comp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/mcxtrace-comps/samples/Single_crystal.comp b/mcxtrace-comps/samples/Single_crystal.comp index bb73913c38..1bd43dea4f 100644 --- a/mcxtrace-comps/samples/Single_crystal.comp +++ b/mcxtrace-comps/samples/Single_crystal.comp @@ -1203,6 +1203,7 @@ SHARE struct sx_abs_data { int muc; // column where mu is to be found double atomic_weight; + double density; // mass density [g/cm^3] double delta_prefactor; t_Table table; }; @@ -1219,6 +1220,7 @@ SHARE exit (-1); } abs->muc = (abs->table.columns == 3 ? 1 : 5); + abs->density = 0; parsing = Table_ParseHeader (abs->table.header, "Z", "A[r]", "rho", NULL); if (parsing) { @@ -1228,7 +1230,11 @@ SHARE info.mat_weight = strtod (parsing[1], NULL); // aka A[r] in g/mol if (parsing[2] && !info.rho) info.rho = strtod (parsing[2], NULL); + if (parsing[2]) + abs->density = strtod (parsing[2], NULL); // nominal density of the absorption material } + if (info.mat_density > 0) + abs->density = info.mat_density; // crystal density from the reflections file wins if (info.rho && info.mat_weight) abs->delta_prefactor = NA * (info.rho * 1e-24) / info.mat_weight * 2.0 * M_PI * RE; @@ -1540,12 +1546,15 @@ TRACE event_counter = 0; V0 = hkl_info.V0; - /* absorption: sigma [cm^2] = atomic_weight [g/mol] / NA [1/mol] * mu [cm^2/g], - then * 1e26 -> [fm^2] and / V0 [Angs^3] -> [1/m]. Independent of the barns flag. */ + /* absorption: linear attenuation = mu [cm^2/g] * density [g/cm^3] = [1/cm], * 100 -> [1/m]. + Without a density, fall back to one atom of atomic_weight per unit cell V0. */ abs_xlen = 0; if (abs_info.muc) { double mu = Table_Value (abs_info.table, ki * K2E, abs_info.muc); - abs_xlen = abs_info.atomic_weight / NA * mu * 1e26 / V0; + if (abs_info.density > 0) + abs_xlen = mu * abs_info.density * 100; + else + abs_xlen = abs_info.atomic_weight / NA * mu * 1e26 / V0; // ponytail: per-atom weight over full cell, too weak for multi-atom cells; give a density } /*look into Compton scattering*/ From 7bbee98a9015032ef246f0a8d66d28883cff4873 Mon Sep 17 00:00:00 2001 From: Peter Willendrup Date: Fri, 30 Oct 2026 07:57:35 +0100 Subject: [PATCH 2/2] McXtrace SSRL: update %Example and %Scan references for density-based absorption Example targets: inverse-variance weighted mean of 3x 1e6 (seeds 1001, 2002, 3003) and 1x 1e7 (seed 4004). Scan references: weighted mean of two 1e7-ray scans (seeds 11, 22), seeds agree within 6%. Co-Authored-By: Claude Opus 5.5 --- .../SSRL_bl_11_2_not_white_src.instr | 10 +++++----- .../SSRL_bl_11_2_white_src.instr | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/mcxtrace-comps/examples/SSRL/SSRL_bl_11_2_not_white_src/SSRL_bl_11_2_not_white_src.instr b/mcxtrace-comps/examples/SSRL/SSRL_bl_11_2_not_white_src/SSRL_bl_11_2_not_white_src.instr index 1de1ac9318..be06ab9f73 100644 --- a/mcxtrace-comps/examples/SSRL/SSRL_bl_11_2_not_white_src/SSRL_bl_11_2_not_white_src.instr +++ b/mcxtrace-comps/examples/SSRL/SSRL_bl_11_2_not_white_src/SSRL_bl_11_2_not_white_src.instr @@ -20,12 +20,12 @@ * A jupyter notebook will soon be available regrouping everything. * You may scan like so for example: * %Scan: mxrun SSRL_bl_11_2_not_white_src.instr -N31 Etohit=6900,7500 -n1e6 Detector: EnergyMonitor_first_I={ -* 4.15283e+11,4.17392e+11,4.14761e+11,4.23379e+11,3.93893e+11,4.24456e+11,4.29582e+11,4.28066e+11, -* 3.79748e+11,3.61699e+11,4.34572e+11,4.42236e+11,4.41343e+11,4.49551e+11,4.23516e+11,3.22482e+11, -* 4.51675e+11,4.52176e+11,4.55269e+11,4.57613e+11,4.60047e+11,4.62858e+11,4.63228e+11,4.65942e+11, -* 3.43853e+11,4.48835e+11,4.73898e+11,4.73046e+11,4.74146e+11,4.79029e+11,4.89455e+11 } +* 1.95875e+11,1.96364e+11,1.96145e+11,2.00332e+11,1.91626e+11,2.01053e+11,2.04481e+11,2.0406e+11, +* 1.97086e+11,1.92699e+11,2.0782e+11,2.112e+11,2.11742e+11,2.1643e+11,2.11361e+11,1.73107e+11, +* 2.18527e+11,2.17407e+11,2.19354e+11,2.20923e+11,2.22335e+11,2.24776e+11,2.25364e+11,2.284e+11, +* 1.82832e+11,2.29721e+11,2.32073e+11,2.31561e+11,2.33712e+11,2.36214e+11,2.41345e+11 } * -* Example: Etohit=6900 Detector: EnergyMonitor_first_I=4.17271e+11 +* Example: Etohit=6900 Detector: EnergyMonitor_first_I=1.94915e+11 * * %Parameters * Etohit: [eV.] Energy used to calculate the bragg angle the monochromator is put at. This is the energy we select. diff --git a/mcxtrace-comps/examples/SSRL/SSRL_bl_11_2_white_src/SSRL_bl_11_2_white_src.instr b/mcxtrace-comps/examples/SSRL/SSRL_bl_11_2_white_src/SSRL_bl_11_2_white_src.instr index c470fb50ee..3743d6faf9 100644 --- a/mcxtrace-comps/examples/SSRL/SSRL_bl_11_2_white_src/SSRL_bl_11_2_white_src.instr +++ b/mcxtrace-comps/examples/SSRL/SSRL_bl_11_2_white_src/SSRL_bl_11_2_white_src.instr @@ -19,12 +19,12 @@ * A jupyter notebook will soon be available regrouping everything. * You may scan like so for example: * %Scan: mxrun SSRL_bl_11_2_white_src.instr -N31 Etohit=6900,7500 detuning_percentage=40 -n1e7 Detector: EnergyMonitor_first_I={ -* 3.53209e+09,3.14111e+09,2.29489e+09,2.09782e+09,2.60157e+09,5.02242e+09,6.82888e+09,5.70155e+09, -* 3.63909e+09,3.66976e+09,4.55549e+09,6.4332e+09,6.3975e+09,5.51199e+09,5.81204e+09,5.14268e+09, -* 5.31883e+09,4.70285e+09,4.76321e+09,4.07989e+09,4.65539e+09,4.37134e+09,4.14511e+09,2.04488e+09, -* 4.0761e+09,3.5035e+09,4.15753e+09,3.83112e+09,3.74015e+09,3.70074e+09,3.86447e+09 } +* 7.76648e+08,7.00468e+08,5.4798e+08,4.99356e+08,5.83372e+08,1.43056e+09,1.8697e+09,1.67391e+09, +* 1.1819e+09,1.17907e+09,1.41455e+09,1.77964e+09,1.74873e+09,1.62426e+09,1.66217e+09,1.47739e+09, +* 1.51503e+09,1.37426e+09,1.42738e+09,1.25464e+09,1.37414e+09,1.36235e+09,1.30217e+09,6.18817e+08, +* 1.18021e+09,1.08398e+09,1.20147e+09,1.14165e+09,1.16105e+09,1.14638e+09,1.14533e+09 } * -* %Example: Etohit=6900 Detector: EnergyMonitor_first_I=1.65837e+10 +* %Example: Etohit=6900 Detector: EnergyMonitor_first_I=3.74674e+09 * * %Parameters * Etohit: [eV.] Energy used to calculate the bragg angle the monochromator is put at. This is the energy we select.