Skip to content

Commit ceab640

Browse files
author
Emmanuel FARHI
committed
mcxtrace: fix fluo sample (xs was not reset to 0)
1 parent 375aae0 commit ceab640

3 files changed

Lines changed: 123 additions & 103 deletions

File tree

mcxtrace-comps/samples/FluoCrystal.comp

Lines changed: 70 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
* Component: FluoCrystal
99
*
1010
* %Identification
11-
* Written by: E. Farhi
11+
* Written by: Emmanuel Farhi (emmanuel.farhi.synchrotron-soleil.fr)
1212
* Date: April 2025
1313
* Origin: Synchrotron SOLEIL
14+
* Release: McXtrace 3.5
1415
*
1516
* Sample model handling absorption, fluorescence, Compton, Rayleigh scattering and single crystal diffraction.
1617
*
@@ -35,8 +36,11 @@
3536
* For instance, a value order>=2 handles e.g. fluorescence iterative cascades
3637
* in the material. Leaving 'order=0' handles the single scattering only.
3738
*
39+
* The single crystal diffraction model is simplified wrt the <b>Single_crystal</b>
40+
* component. Use that latter with a Fluorescence in a GROUP for more complex features.
41+
*
3842
* Example: FluoCrystal(material="LaB6.cif",
39-
* xwidth=0.001,yheight=0.001,zdepth=0.0001, p_interact=0.99, mosaic=1)
43+
* xwidth=0.001,yheight=0.001,zdepth=0.0001, p_interact=0.99, mosaic=3)
4044
*
4145
* <b>Sample shape:</b>
4246
* Sample shape may be a cylinder, a sphere, a box or any other shape
@@ -85,13 +89,13 @@
8589
* In addition, it may be desirable to define a 'target' for the fluorescence
8690
* processes via e.g. the 'target_index' and the 'focus_xw / focus_yh' options.
8791
* This target should e.g. be the SDD area.
88-
* The crystal scattering can be focused along an horizontal tore via the
89-
* 'sx_d_phi' and 'sx_sign' options. To get a vertical tore, rotate
90-
* the sample by 90 deg around Z.
9192
*
9293
* This sample component can advantageously benefit from the SPLIT feature, e.g.
9394
* SPLIT COMPONENT sample = FluoCrystal(...)
9495
*
96+
* If you get strange results, check the crystal mosaicity and delta(d)/d parameters,
97+
* as this component is not suited for ideal/perfect mosaic crystals.
98+
*
9599
* <b>Detector artifacts:</b>
96100
* This component also simulates the escape and time coincidence peaks in a close-by
97101
* detector (e.g. SDD). The first process corresponds with a fluorescence excitation within
@@ -144,36 +148,30 @@
144148
* target_z: [m] Position of target to focus at, along Z (for fluorescence).
145149
* flag_compton: [1] When 0, the Compton scattering is ignored.
146150
* flag_rayleigh: [1] When 0, the Rayleigh scattering is ignored.
147-
* flag_sx: [1] When 0, the crystal diffraction is ignored.
151+
* flag_sx: [1] When 0, the crystal diffraction is ignored.
148152
* flag_lorentzian:[1] When 1, the fluorescence line shapes are assumed to be Lorentzian, else Gaussian.
149153
* escape_ratio: [1] Detector escape peak ratio, e.g. 0.01-0.02. 0 inactivates.
150154
* escape_energy:[keV] Detector escape peak energy, e.g. 1.739 for Si, 9.886 for Ge.
151155
* pileup_ratio: [1] Sum aka time coincidence aka pile-up detector peak ratio, e.g. 0.01-0.02. 0 inactivates.
152-
* sx_barns: [1] Flag to indicate if |F|^2 from 'material' is in barns or fm^2, (barns=1 for laz, barns=0 for lau type files).
153-
* sx_d_phi: [deg] Angle corresponding to the vertical angular range to focus to, e.g. detector height. 0 for no focusing.
154-
* sx_delta_d_d: [1] Lattice spacing variance, gaussian RMS (longitudinal mosaic)
155-
* sx_DW: [1] Global Debye-Waller factor when the 'DW' column is not available. Use 1 if included in F2.
156-
* sx_format: [{}] List of structure file column indexes. See the PowderN component.
157-
* sx_nb_atoms:[1] Number of sub-unit per unit cell, that is ratio of sigma for chemical formula to sigma per unit cell.
158-
* sx_refl: [str] A CIF/LAZ/LAU reflection file as for PowderN. When not given, 'material' is used. Specify it when 'material' is a chemical formula.
159-
* sx_sign: [1] Sign of the scattering angle. If 0, the sign is chosen randomly (left and right).
160-
* sx_Vc: [AA^3] Volume of unit cell=nb atoms per cell/density of atoms.
161-
* sx_mosaic: [arc minutes] Crystal mosaic (isotropic), gaussian RMS. Puts the crystal in the isotropic mosaic model state, thus disregarding other mosaicity parameters.
162-
* sx_mosaic_a: [arc minutes] Horizontal (rotation around lattice vector a) mosaic (anisotropic), gaussian RMS. Put the crystal in the anisotropic crystal vector state. I.e. model mosaicity through rotation around the crystal lattice vectors. Has precedence over in-plane mosaic model.
163-
* sx_mosaic_b: [arc minutes] Vertical (rotation around lattice vector b) mosaic (anisotropic), gaussian RMS.
164-
* sx_mosaic_c: [arc minutes] Out-of-plane (Rotation around lattice vector c) mosaic (anisotropic), gaussian RMS
165-
* sx_mosaic_AB: [arc_minutes, arc_minutes,1, 1, 1, 1, 1, 1] In Plane mosaic rotation and plane vectors (anisotropic), mosaic_A, mosaic_B, A_h,A_k,A_l, B_h,B_k,B_l. Puts the crystal in the in-plane mosaic state. Vectors A and B define plane in which the crystal roation is defined, and mosaic_A, mosaic_B, denotes the resp. mosaicities (gaussian RMS) with respect to the two reflections chosen by A and B (Miller indices).
166-
* sx_recip_cell: [1] Choice of direct/reciprocal (0/1) unit cell definition
167-
* sx_ax: [AA or AA^-1] Coordinates of first (direct/recip) unit cell vector
168-
* sx_ay: [AA or AA^-1] a on y axis
169-
* sx_az: [AA or AA^-1] a on z axis
170-
* sx_bx: [AA or AA^-1] Coordinates of second (direct/recip) unit cell vector
171-
* sx_by: [AA or AA^-1] b on y axis
172-
* sx_bz: [AA or AA^-1] b on z axis
173-
* sx_cx: [AA or AA^-1] Coordinates of third (direct/recip) unit cell vector
174-
* sx_cy: [AA or AA^-1] c on y axis
175-
* sx_cz: [AA or AA^-1] c on z axis
176156
* order: [1] Limit multiple fluorescence up to given order. Last iteration is absorption only.
157+
* sx_refl: [str] A CIF/LAZ/LAU reflection file as for PowderN. When not given, 'material' is used. Specify it when 'material' is a chemical formula.
158+
* barns: [1] Flag to indicate if |F|^2 from 'material' is in barns or fm^2, (barns=1 for laz/cif, barns=0 for lau type files).
159+
* delta_d_d: [1] Lattice spacing variance, gaussian RMS (longitudinal mosaic) e.g. 1e-4 to 1e-3.
160+
* mosaic: [arc min] Crystal mosaic (isotropic), gaussian RMS. Puts the crystal in the isotropic mosaic model state, thus disregarding other mosaicity parameters, e.g. 1-10.
161+
* mosaic_a: [arc min] Horizontal (rotation around lattice vector a) mosaic (anisotropic), gaussian RMS. Put the crystal in the anisotropic crystal vector state. I.e. model mosaicity through rotation around the crystal lattice vectors. Has precedence over in-plane mosaic model.
162+
* mosaic_b: [arc min] Vertical (rotation around lattice vector b) mosaic (anisotropic), gaussian RMS.
163+
* mosaic_c: [arc min] Out-of-plane (Rotation around lattice vector c) mosaic (anisotropic), gaussian RMS
164+
* mosaic_AB: [arc_minutes, arc_minutes,1, 1, 1, 1, 1, 1] In Plane mosaic rotation and plane vectors (anisotropic), mosaic_A, mosaic_B, A_h,A_k,A_l, B_h,B_k,B_l. Puts the crystal in the in-plane mosaic state. Vectors A and B define plane in which the crystal roation is defined, and mosaic_A, mosaic_B, denotes the resp. mosaicities (gaussian RMS) with respect to the two reflections chosen by A and B (Miller indices).
165+
* recip_cell: [1] Choice of direct/reciprocal (0/1) unit cell definition
166+
* ax: [AA or AA^-1] Coordinates of first (direct/recip) unit cell vector
167+
* ay: [AA or AA^-1] a on y axis
168+
* az: [AA or AA^-1] a on z axis
169+
* bx: [AA or AA^-1] Coordinates of second (direct/recip) unit cell vector
170+
* by: [AA or AA^-1] b on y axis
171+
* bz: [AA or AA^-1] b on z axis
172+
* cx: [AA or AA^-1] Coordinates of third (direct/recip) unit cell vector
173+
* cy: [AA or AA^-1] c on y axis
174+
* cz: [AA or AA^-1] c on z axis
177175
*
178176
* CALCULATED PARAMETERS:
179177
* type: scattering event type 0=fluorescence, 1=Rayleigh, 2=Compton, 3=transmit (absorbsion), 4=diffraction, 5=detector escape peak, 6=detector pile-up/sum/coincidence peak
@@ -207,14 +205,15 @@ SETTING PARAMETERS(
207205
target_x = 0, target_y = 0, target_z = 0, focus_r = 0,
208206
focus_xw=0, focus_yh=0, focus_aw=0, focus_ah=0, int target_index=0,
209207
int flag_compton=1, int flag_rayleigh=1, int flag_lorentzian=1,
210-
string sx_refl="",
211-
int flag_sx=1, sx_delta_d_d=1e-4, int sx_barns=1, vector sx_mosaic_AB={0,0, 0,0,0, 0,0,0},
212-
sx_recip_cell=0,
213-
sx_ax = 0, sx_ay = 0, sx_az = 0,
214-
sx_bx = 0, sx_by = 0, sx_bz = 0,
215-
sx_cx = 0, sx_cy = 0, sx_cz = 0,
216-
sx_aa=0, sx_bb=0, sx_cc=0,
217-
sx_mosaic = -1, sx_mosaic_a = -1, sx_mosaic_b = -1, sx_mosaic_c = -1,
208+
string sx_refl="", int flag_sx=1,
209+
delta_d_d=1e-3, int barns=1,
210+
recip_cell=0,
211+
ax = 0, ay = 0, az = 0,
212+
bx = 0, by = 0, bz = 0,
213+
cx = 0, cy = 0, cz = 0,
214+
aa=0, bb=0, cc=0,
215+
vector mosaic_AB={0,0, 0,0,0, 0,0,0},
216+
mosaic = 3, mosaic_a = -1, mosaic_b = -1, mosaic_c = -1,
218217
escape_ratio=0, escape_energy=1.739,
219218
pileup_ratio=0,
220219
int order=1)
@@ -257,6 +256,7 @@ SHARE COPY Single_crystal EXTEND %{
257256
int i_line;
258257

259258
if (xs == NULL) return 0;
259+
for(i_line=0; i_line<=COMPTON; i_line++) xs[i_line]=0;
260260

261261
// loop on possible fluorescence lines
262262
for (i_line=0; i_line<XRAYLIB_LINES_MAX; i_line++) {
@@ -279,6 +279,7 @@ SHARE COPY Single_crystal EXTEND %{
279279
*/
280280
int XRMC_SelectFromDistribution(double x_arr[], int N)
281281
{
282+
if (x_arr == NULL || N <=0) return (0);
282283
double x=rand01()*x_arr[N-1];
283284
if (x<x_arr[0]) { // x is smaller than lower limit
284285
return 0;
@@ -308,7 +309,7 @@ SHARE COPY Single_crystal EXTEND %{
308309
double sum_xs, *cum_xs;
309310
int i;
310311

311-
if (nb_processes < 1) return 0;
312+
if (xs == NULL || nb_processes < 1 || nb_processes > TRANSMISSION) return 0;
312313
cum_xs = malloc((nb_processes+1)*sizeof(double));
313314
if (!cum_xs) return 0;
314315
cum_xs[0]=sum_xs=0;
@@ -350,6 +351,7 @@ SHARE COPY Single_crystal EXTEND %{
350351
{
351352
// non_space_count to keep the frequency of non space characters
352353
int non_space_count = 0;
354+
if (string == NULL) return NULL;
353355

354356
//Traverse a string and if it is non space character then, place it at index non_space_count
355357
for (int i = 0; string[i] != '\0'; i++)
@@ -373,7 +375,8 @@ SHARE COPY Single_crystal EXTEND %{
373375

374376
int ret = 0;
375377
char Line[65535];
376-
int flag_found_cif=0;
378+
int flag_found_cif=0;
379+
if (filename == NULL || formula == NULL) return (0);
377380
FILE *file = Open_File(filename, "r", NULL);
378381
if (!file)
379382
exit(fprintf(stderr, "%s: ERROR: can not open file %s\n",
@@ -542,23 +545,23 @@ INITIALIZE %{
542545
hkl_info.ctr_FT2 =NULL;
543546
hkl_info.ctr_dir =NULL;
544547
/* transfer input parameters */
545-
hkl_info.m_delta_d_d = sx_delta_d_d;
548+
hkl_info.m_delta_d_d = delta_d_d;
546549
hkl_info.m_a = 0;
547550
hkl_info.m_b = 0;
548551
hkl_info.m_c = 0;
549-
hkl_info.m_aa = sx_aa;
550-
hkl_info.m_bb = sx_bb;
551-
hkl_info.m_cc = sx_cc;
552-
hkl_info.m_ax = sx_ax;
553-
hkl_info.m_ay = sx_ay;
554-
hkl_info.m_az = sx_az;
555-
hkl_info.m_bx = sx_bx;
556-
hkl_info.m_by = sx_by;
557-
hkl_info.m_bz = sx_bz;
558-
hkl_info.m_cx = sx_cx;
559-
hkl_info.m_cy = sx_cy;
560-
hkl_info.m_cz = sx_cz;
561-
hkl_info.recip= sx_recip_cell;
552+
hkl_info.m_aa = aa;
553+
hkl_info.m_bb = bb;
554+
hkl_info.m_cc = cc;
555+
hkl_info.m_ax = ax;
556+
hkl_info.m_ay = ay;
557+
hkl_info.m_az = az;
558+
hkl_info.m_bx = bx;
559+
hkl_info.m_by = by;
560+
hkl_info.m_bz = bz;
561+
hkl_info.m_cx = cx;
562+
hkl_info.m_cy = cy;
563+
hkl_info.m_cz = cz;
564+
hkl_info.recip= recip_cell;
562565

563566
/* default format h,k,l,F,F2 */
564567
hkl_info.column_order[0]=1;
@@ -569,16 +572,16 @@ INITIALIZE %{
569572
hkl_info.kix = hkl_info.kiy = hkl_info.kiz = 0;
570573
hkl_info.nb_reuses = hkl_info.nb_refl = hkl_info.nb_refl_count = 0;
571574
hkl_info.tau_count = 0;
572-
hkl_info.flag_barns= sx_barns;
573-
double* mosaic_ABin = sx_mosaic_AB;
575+
hkl_info.flag_barns= barns;
576+
double* mosaic_ABin = mosaic_AB;
574577

575578
if (!sx_refl || !strlen(sx_refl) || !strcmp(sx_refl, "NULL") || !strcmp(sx_refl, "0"))
576579
strcpy(sx_refl, material);
577-
i = read_hkl_data(sx_refl, &hkl_info, &hkl_list, sx_mosaic, sx_mosaic_a, sx_mosaic_b, sx_mosaic_c, mosaic_ABin,
580+
i = read_hkl_data(sx_refl, &hkl_info, &hkl_list, mosaic, mosaic_a, mosaic_b, mosaic_c, mosaic_ABin,
578581
hkl_info.ctr_size,hkl_info.ctr_k,hkl_info.ctr_FT2,hkl_info.ctr_dir);
579582
if (i == 0) {
580583
MPI_MASTER(
581-
fprintf(stderr,"WARNING: FluoCrystal: %s: sx_mosaic or material file %s is not valid (CIF/LAU). Ignoring diffraction process.\n",
584+
fprintf(stderr,"WARNING: FluoCrystal: %s: mosaic or material file %s is not valid (CIF/LAU). Ignoring diffraction process.\n",
582585
NAME_CURRENT_COMP, sx_refl);
583586
);
584587
flag_sx=0;
@@ -873,9 +876,9 @@ do { /* while (intersect) Loop over multiple scattering events */
873876
XRMC_CrossSections(Z, E, xs_Z); // [barn/atom]
874877
sigma_barn += frac*CSb_Total(Z, E, NULL); // Fluo+Compton+Rayleigh
875878
cum_xs_fluo[i_Z+1] = cum_xs_fluo[i_Z] +frac*xs_Z[FLUORESCENCE];
876-
cum_xs_Compton[i_Z+1] = cum_xs_Compton[i_Z] +frac*xs_Z[COMPTON];
877879
cum_xs_Rayleigh[i_Z+1] = cum_xs_Rayleigh[i_Z]+frac*xs_Z[RAYLEIGH];
878-
for (i=0; i<3; i++) { xs[i] += frac*xs_Z[i]; }
880+
cum_xs_Compton[i_Z+1] = cum_xs_Compton[i_Z] +frac*xs_Z[COMPTON];
881+
for (i=0; i<COMPTON+1; i++) { xs[i] += frac*xs_Z[i]; }
879882
} // for Z in compound
880883

881884
if (flag_sx) {
@@ -888,10 +891,8 @@ do { /* while (intersect) Loop over multiple scattering events */
888891
xs[DIFFRACTION] = coh_xsect;
889892
sigma_barn += xs[DIFFRACTION];
890893
} else {
891-
coh_refl = 0;
892-
coh_xsect = 0;
893-
tau_count = 0;
894-
xs[DIFFRACTION] = 0;
894+
xs[DIFFRACTION] = coh_refl = coh_xsect = 0;
895+
tau_count = 0;
895896
}
896897

897898
// store values into cache for SPLIT
@@ -902,6 +903,9 @@ do { /* while (intersect) Loop over multiple scattering events */
902903
}
903904
reuse_cum_xs_diffraction = xs[DIFFRACTION];
904905
reuse_sigma_barn = sigma_barn;
906+
hkl_info.coh_refl = coh_refl;
907+
hkl_info.coh_xsect = coh_xsect;
908+
hkl_info.tau_count = tau_count;
905909

906910
} else {
907911
// reuse cached values (SPLIT)
@@ -912,9 +916,8 @@ do { /* while (intersect) Loop over multiple scattering events */
912916
xs[FLUORESCENCE] += reuse_cum_xs_fluo[i_Z+1];
913917
xs[COMPTON] += reuse_cum_xs_Compton[i_Z+1];
914918
xs[RAYLEIGH] += reuse_cum_xs_Rayleigh[i_Z+1];
915-
xs[DIFFRACTION] = reuse_cum_xs_diffraction;
916919
}
917-
920+
xs[DIFFRACTION] = reuse_cum_xs_diffraction;
918921
sigma_barn = reuse_sigma_barn;
919922
if (flag_sx) {
920923
coh_refl = hkl_info.coh_refl;
@@ -979,7 +982,7 @@ do { /* while (intersect) Loop over multiple scattering events */
979982
if (dsigma < 1) p *= dsigma; // < 1
980983

981984
/* MC choose process from cross sections 'xs': fluo, Compton, Rayleigh, diff */
982-
type = XRMC_SelectInteraction(xs, 4);
985+
type = XRMC_SelectInteraction(xs, DIFFRACTION+1); // up to DIFFRACTION
983986

984987
/* choose Z (element) on associated XS, taking into account mass-fractions */
985988
switch (type) {

0 commit comments

Comments
 (0)