Skip to content

Commit e0c3024

Browse files
authored
Mcxtrace fluo fix : fix in powder select - use gaussian line shape (#1994)
* mcxtrace: fluo: default line-shape Gaussian, fix in powder line search * mcxtrace: FluoPowder: final touch
1 parent 52e9def commit e0c3024

3 files changed

Lines changed: 107 additions & 109 deletions

File tree

mcxtrace-comps/samples/FluoCrystal.comp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ SETTING PARAMETERS(
204204
p_interact=0,
205205
target_x = 0, target_y = 0, target_z = 0, focus_r = 0,
206206
focus_xw=0, focus_yh=0, focus_aw=0, focus_ah=0, int target_index=0,
207-
int flag_compton=1, int flag_rayleigh=1, int flag_lorentzian=1,
207+
int flag_compton=1, int flag_rayleigh=1, int flag_lorentzian=0,
208208
string sx_refl="", int flag_sx=1,
209209
delta_d_d=1e-3, int barns=1,
210210
recip_cell=0,
@@ -309,7 +309,7 @@ SHARE COPY Single_crystal EXTEND %{
309309
double sum_xs, *cum_xs;
310310
int i;
311311

312-
if (xs == NULL || nb_processes < 1 || nb_processes > TRANSMISSION) return 0;
312+
if (xs == NULL || nb_processes < 1) return 0;
313313
cum_xs = malloc((nb_processes+1)*sizeof(double));
314314
if (!cum_xs) return 0;
315315
cum_xs[0]=sum_xs=0;
@@ -1127,7 +1127,7 @@ do { /* while (intersect) Loop over multiple scattering events */
11271127
/* exit if multiple scattering order has been reached */
11281128
if (!order) break; // skip final absorption
11291129
// stop when order has been reached, or weighting is very low
1130-
if (order && (event_counter >= order || p/pi < 1e-7)) { force_transmit=1; }
1130+
if (order && (event_counter >= order || p/pi < 1e-15)) { force_transmit=1; }
11311131

11321132
} // if intersect (scatter)
11331133
} while(intersect); /* end do (intersect) (multiple scattering loop) */

mcxtrace-comps/samples/FluoPowder.comp

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ SETTING PARAMETERS(
193193
p_interact=0,
194194
target_x = 0, target_y = 0, target_z = 0, focus_r = 0,
195195
focus_xw=0, focus_yh=0, focus_aw=0, focus_ah=0, int target_index=0,
196-
int flag_compton=1, int flag_rayleigh=1, int flag_lorentzian=1, int flag_powder=1,
196+
int flag_compton=1, int flag_rayleigh=1, int flag_lorentzian=0, int flag_powder=1,
197197
string powder_refl="",
198198
vector powder_format={0,0,0,0,0,0,0,0}, Vc=0, delta_d_d=0, DW=0,
199199
d_phi=0, int nb_atoms=1, int barns=1, int tth_sign=0,
@@ -292,7 +292,7 @@ SHARE COPY PowderN EXTEND %{
292292
double sum_xs, *cum_xs;
293293
int i;
294294

295-
if (xs == NULL || nb_processes < 1 || nb_processes > TRANSMISSION) return 0;
295+
if (xs == NULL || nb_processes < 1) return 0;
296296
cum_xs = malloc((nb_processes+1)*sizeof(double));
297297
if (!cum_xs) return 0;
298298
cum_xs[0]=sum_xs=0;
@@ -474,7 +474,6 @@ DECLARE COPY PowderN EXTEND %{
474474
INITIALIZE %{
475475

476476
/* energies en [keV], angles in [radians], XRL CSb cross sections are in [barn/atom] */
477-
double E0, dE;
478477
xrl_error *error = NULL;
479478
int i;
480479

@@ -959,9 +958,9 @@ do { /* while (intersect) Loop over multiple scattering events */
959958

960959
if (intersect) { /* scattering event */
961960
int i_Z=-1, Z, line=-1;
962-
double solid_angle;
963-
double theta, dsigma, alpha;
964-
double Ef, dE;
961+
double solid_angle=0;
962+
double theta=0, dsigma=0, alpha=0;
963+
double Ef=0, dE=0;
965964
double kf=k, kf_x, kf_y, kf_z; // next particle direction
966965

967966
/* correct for XS total(photo+Compton+Rayleigh+Powder) > sum(fluo+Compton+Rayleigh+Powder) */
@@ -1040,12 +1039,12 @@ do { /* while (intersect) Loop over multiple scattering events */
10401039
{ /* relate height of detector to the height on DS cone */
10411040
arg = sin(d_phi*DEG2RAD/2)/sin(2*theta);
10421041
/* If full Debye-Scherrer cone is within d_phi, don't focus */
1043-
if (arg < -1 || arg > 1) alpha = 0;
1042+
if (arg < -1 || arg > 1) d_phi = alpha = 0;
10441043
/* Otherwise, determine alpha to rotate from scattering plane
10451044
* into d_phi focusing area */
10461045
else alpha = 2*asin(arg);
10471046
}
1048-
if (alpha) {
1047+
if (d_phi && alpha) {
10491048
/* Focusing */
10501049
alpha = fabs(alpha);
10511050
alpha0 = 0.5*randpm1()*alpha;
@@ -1110,13 +1109,13 @@ do { /* while (intersect) Loop over multiple scattering events */
11101109
if (Ex!=0 || Ey!=0 || Ez!=0){
11111110
double EE=sqrt(Ex*Ex+Ey*Ey+Ez*Ez);
11121111
double s=scalar_prod(kf_x,kf_y,kf_z,Ex,Ey,Ez)/EE;
1113-
p*=(1-s)*(1-s);
1112+
p *= (1-s)*(1-s);
11141113
}else{
11151114
/*unpolarized light in - means an effective reduction according to only theta*/
1116-
p*=(1+cos(theta)*cos(theta))*0.5;
1115+
p *= (1+cos(theta)*cos(theta))*0.5;
11171116
}
1118-
if (alpha) {
1119-
p *= alpha/PI;
1117+
if (d_phi && alpha) {
1118+
p *= alpha/PI;
11201119
}
11211120
n_diff++;
11221121
p_diff += p;
@@ -1151,7 +1150,7 @@ do { /* while (intersect) Loop over multiple scattering events */
11511150
/* exit if multiple scattering order has been reached */
11521151
if (!order) break; // skip final absorption
11531152
// stop when order has been reached, or weighting is very low
1154-
if (order && (event_counter >= order || p/pi < 1e-7)) { force_transmit=1; }
1153+
if (order && (event_counter >= order || p/pi < 1e-15)) { force_transmit=1; }
11551154

11561155
} // if intersect (scatter)
11571156
} while(intersect); /* end do (intersect) (multiple scattering loop) */

mcxtrace-comps/samples/Fluorescence.comp

Lines changed: 92 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ SETTING PARAMETERS(
180180
p_interact=0,
181181
target_x = 0, target_y = 0, target_z = 0, focus_r = 0,
182182
focus_xw=0, focus_yh=0, focus_aw=0, focus_ah=0, int target_index=0,
183-
int flag_compton=1, int flag_rayleigh=1, int flag_lorentzian=1,
183+
int flag_compton=1, int flag_rayleigh=1, int flag_lorentzian=0,
184184
escape_ratio=0, escape_energy=1.739,
185185
pileup_ratio=0,
186186
int order=1)
@@ -217,99 +217,99 @@ SHARE %{
217217
* https://github.com/golosio/xrmc src/photon/photon.cpp (c) Bruno Golosio
218218
*/
219219

220-
/* XRMC_CrossSections: Compute interaction cross sections in [barn/atom]
221-
* Return total cross section, given Z and E0:
222-
* total_xs = XRMC_CrossSections(Z, E0, xs[3]);
223-
*/
224-
double XRMC_CrossSections(int Z, double E0, double *xs) {
225-
int i_line;
226-
227-
if (xs == NULL) return 0;
228-
for(i_line=0; i_line<=COMPTON; i_line++) xs[i_line]=0;
229-
230-
// loop on possible fluorescence lines
231-
for (i_line=0; i_line<XRAYLIB_LINES_MAX; i_line++) {
232-
// cumulative sum of the line cross sections
233-
xs[FLUORESCENCE] += CSb_FluorLine(Z, -i_line, E0, NULL); /* XRayLib */
234-
}
220+
/* XRMC_CrossSections: Compute interaction cross sections in [barn/atom]
221+
* Return total cross section, given Z and E0:
222+
* total_xs = XRMC_CrossSections(Z, E0, xs[3]);
223+
*/
224+
double XRMC_CrossSections(int Z, double E0, double *xs) {
225+
int i_line;
226+
227+
if (xs == NULL) return 0;
228+
for(i_line=0; i_line<=COMPTON; i_line++) xs[i_line]=0;
229+
230+
// loop on possible fluorescence lines
231+
for (i_line=0; i_line<XRAYLIB_LINES_MAX; i_line++) {
232+
// cumulative sum of the line cross sections
233+
xs[FLUORESCENCE] += CSb_FluorLine(Z, -i_line, E0, NULL); /* XRayLib */
234+
}
235235

236-
// coherent and incoherent cross sections
237-
xs[RAYLEIGH] = CSb_Rayl( Z, E0, NULL);
238-
xs[COMPTON] = CSb_Compt(Z, E0, NULL);
239-
240-
// total interaction cross section, should converge to CSb_Total(Z, E0, NULL)
241-
return xs[FLUORESCENCE] + xs[RAYLEIGH] + xs[COMPTON];
242-
} // XRMC_CrossSections
243-
244-
/* XRMC_SelectFromDistribution: select a random element from a distribution
245-
* index = XRMC_SelectFromDistribution(cum_sum[N], N);
246-
* index is returned within 0 and N-1
247-
* The x_arr must be a continuously increasing cumulated sum, which last element is the max
248-
*/
249-
int XRMC_SelectFromDistribution(double x_arr[], int N)
250-
{
251-
if (x_arr == NULL || N <=0) return (0);
252-
double x=rand01()*x_arr[N-1];
253-
if (x<x_arr[0]) { // x is smaller than lower limit
254-
return 0;
255-
}
256-
if (x>=x_arr[N-1]) { // x is greater or equal to upper limit
257-
return N-1;
258-
}
259-
int id=0, iu=N-1; // lower and upper index of the subarray to search
260-
while (iu-id>1) { // search until the size of the subarray to search is >1
261-
int im = (id + iu)/2; // use the midpoint for equal partition
262-
// decide which subarray to search
263-
if (x>=x_arr[im]) id=im; // change min index to search upper subarray
264-
else iu=im; // change max index to search lower subarray
265-
}
236+
// coherent and incoherent cross sections
237+
xs[RAYLEIGH] = CSb_Rayl( Z, E0, NULL);
238+
xs[COMPTON] = CSb_Compt(Z, E0, NULL);
239+
240+
// total interaction cross section, should converge to CSb_Total(Z, E0, NULL)
241+
return xs[FLUORESCENCE] + xs[RAYLEIGH] + xs[COMPTON];
242+
} // XRMC_CrossSections
243+
244+
/* XRMC_SelectFromDistribution: select a random element from a distribution
245+
* index = XRMC_SelectFromDistribution(cum_sum[N], N);
246+
* index is returned within 0 and N-1
247+
* The x_arr must be a continuously increasing cumulated sum, which last element is the max
248+
*/
249+
int XRMC_SelectFromDistribution(double x_arr[], int N)
250+
{
251+
if (x_arr == NULL || N <=0) return (0);
252+
double x=rand01()*x_arr[N-1];
253+
if (x<x_arr[0]) { // x is smaller than lower limit
254+
return 0;
255+
}
256+
if (x>=x_arr[N-1]) { // x is greater or equal to upper limit
257+
return N-1;
258+
}
259+
int id=0, iu=N-1; // lower and upper index of the subarray to search
260+
while (iu-id>1) { // search until the size of the subarray to search is >1
261+
int im = (id + iu)/2; // use the midpoint for equal partition
262+
// decide which subarray to search
263+
if (x>=x_arr[im]) id=im; // change min index to search upper subarray
264+
else iu=im; // change max index to search lower subarray
265+
}
266266

267-
return id;
268-
} // XRMC_SelectFromDistribution
267+
return id;
268+
} // XRMC_SelectFromDistribution
269269

270-
/* XRMC_SelectInteraction: select interaction type Fluo/Compton/Rayleigh
271-
* Return the interaction type from a random choice within cross sections 'xs'
272-
* type = XRMC_SelectInteraction(xs[3], 3);
273-
* 'xs' is computed with XRMC_CrossSections.
274-
* type is one of FLUORESCENCE | RAYLEIGH | COMPTON
275-
*/
276-
int XRMC_SelectInteraction(double *xs, int nb_processes)
277-
{
278-
double sum_xs, cum_xs[5];
279-
int i;
280-
281-
if (xs == NULL || nb_processes < 1 || nb_processes > TRANSMISSION) return 0;
282-
cum_xs[0]=sum_xs=0;
283-
for (i=0; i< nb_processes; i++) {
284-
sum_xs += xs[i];
285-
cum_xs[i+1]= sum_xs;
286-
}
287-
return XRMC_SelectFromDistribution(cum_xs, nb_processes+1);
288-
} // XRMC_SelectInteraction
270+
/* XRMC_SelectInteraction: select interaction type Fluo/Compton/Rayleigh
271+
* Return the interaction type from a random choice within cross sections 'xs'
272+
* type = XRMC_SelectInteraction(xs[3], 3);
273+
* 'xs' is computed with XRMC_CrossSections.
274+
* type is one of FLUORESCENCE | RAYLEIGH | COMPTON
275+
*/
276+
int XRMC_SelectInteraction(double *xs, int nb_processes)
277+
{
278+
double sum_xs, cum_xs[5];
279+
int i;
280+
281+
if (xs == NULL || nb_processes < 1) return 0;
282+
cum_xs[0]=sum_xs=0;
283+
for (i=0; i< nb_processes; i++) {
284+
sum_xs += xs[i];
285+
cum_xs[i+1]= sum_xs;
286+
}
287+
return XRMC_SelectFromDistribution(cum_xs, nb_processes+1);
288+
} // XRMC_SelectInteraction
289289

290-
/* XRMC_SelectFluorescenceEnergy: select outgoing fluo photon energy, when incoming with 'E0'
291-
* Ef = XRMC_SelectFluorescenceEnergy(Z, E0, &dE);
292-
*/
293-
double XRMC_SelectFluorescenceEnergy(int Z, double E0, double *dE)
294-
{
295-
int i_line;
296-
double sum_xs, cum_xs_lines[XRAYLIB_LINES_MAX+1];
297-
298-
// compute cumulated XS for all fluo lines
299-
cum_xs_lines[0] = sum_xs = 0;
300-
for (i_line=0; i_line<XRAYLIB_LINES_MAX; i_line++) { // loop on fluorescent lines
301-
double xs = CSb_FluorLine(Z, -i_line, E0, NULL); /* XRayLib */
302-
// when a line is inactive: E=xs=0
303-
sum_xs += xs;
304-
cum_xs_lines[i_line+1] = sum_xs; // cumulative sum of their cross sections
305-
}
306-
// select randomly one of these lines
307-
i_line = XRMC_SelectFromDistribution(cum_xs_lines, XRAYLIB_LINES_MAX); // extract a line
308-
// get the K shell line width as approximation of fluorescence line width
309-
if (dE) *dE = AtomicLevelWidth(Z, K_SHELL, NULL); // keV
290+
/* XRMC_SelectFluorescenceEnergy: select outgoing fluo photon energy, when incoming with 'E0'
291+
* Ef = XRMC_SelectFluorescenceEnergy(Z, E0, &dE);
292+
*/
293+
double XRMC_SelectFluorescenceEnergy(int Z, double E0, double *dE)
294+
{
295+
int i_line;
296+
double sum_xs, cum_xs_lines[XRAYLIB_LINES_MAX+1];
297+
298+
// compute cumulated XS for all fluo lines
299+
cum_xs_lines[0] = sum_xs = 0;
300+
for (i_line=0; i_line<XRAYLIB_LINES_MAX; i_line++) { // loop on fluorescent lines
301+
double xs = CSb_FluorLine(Z, -i_line, E0, NULL); /* XRayLib */
302+
// when a line is inactive: E=xs=0
303+
sum_xs += xs;
304+
cum_xs_lines[i_line+1] = sum_xs; // cumulative sum of their cross sections
305+
}
306+
// select randomly one of these lines
307+
i_line = XRMC_SelectFromDistribution(cum_xs_lines, XRAYLIB_LINES_MAX); // extract a line
308+
// get the K shell line width as approximation of fluorescence line width
309+
if (dE) *dE = AtomicLevelWidth(Z, K_SHELL, NULL); // keV
310310

311-
return LineEnergy(Z, -i_line, NULL); // fluorescent line energy
312-
} // XRMC_SelectFluorescenceEnergy
311+
return LineEnergy(Z, -i_line, NULL); // fluorescent line energy
312+
} // XRMC_SelectFluorescenceEnergy
313313

314314
// Function removing spaces from string
315315
char * removeSpacesFromStr(char *string)
@@ -453,7 +453,6 @@ DECLARE %{
453453
INITIALIZE %{
454454

455455
/* energies en [keV], angles in [radians], XRL CSb cross sections are in [barn/atom] */
456-
double E0, dE;
457456
xrl_error *error = NULL;
458457
int i;
459458

@@ -616,7 +615,7 @@ double ki,pi;
616615
/* Store Initial photon state */
617616
k = ki = sqrt(kx*kx+ky*ky+kz*kz); // Angs-1
618617
E = K2E*k; // keV
619-
pi = p; // used to test for multiple fluo weighting and order cutoff
618+
pi = p; // used to test for multiple fluo weighting and order cutoff
620619

621620
do { /* while (intersect) Loop over multiple scattering events */
622621

@@ -863,7 +862,7 @@ do { /* while (intersect) Loop over multiple scattering events */
863862
i_Z = XRMC_SelectFromDistribution(cum_xs_Compton, compound->nElements+1);
864863
break;
865864
default:
866-
printf("%s: WARNING: process %i unknown. Absorb.\n", NAME_CURRENT_COMP, type);
865+
// printf("%s: WARNING: process %i unknown. Absorb.\n", NAME_CURRENT_COMP, type);
867866
ABSORB;
868867
}
869868
Z = compound->Elements[i_Z];
@@ -943,7 +942,7 @@ do { /* while (intersect) Loop over multiple scattering events */
943942
/* exit if multiple scattering order has been reached */
944943
if (!order) break; // skip final absorption
945944
// stop when order has been reached, or weighting is very low
946-
if (order && (event_counter >= order || p/pi < 1e-7)) { force_transmit=1; }
945+
if (order && (event_counter >= order || p/pi < 1e-15)) { force_transmit=1; }
947946

948947
} // if intersect (scatter)
949948
} while(intersect); /* end do (intersect) (multiple scattering loop) */

0 commit comments

Comments
 (0)