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
|
/*******************************************************************************
* McXtrace, x-ray tracing package
* Copyright, All rights reserved
* DTU Physics, Kgs. Lyngby, Denmark
* Synchrotron SOLEIL, Saint-Aubin, France
*
* Component: SAXSQMonitor
*
* %Identification
* Written by: Martin Cramer Pedersen (mcpe@nbi.dk)
* Based on a SANS-component in McStas by Søren Kynde
* Date: May 2, 2012
* Origin: KU-Science
* Release: McXtrace 1.0
*
* A circular detector measuring the radial average of intensity as a function
* of the momentum transform in the sample.
*
* %Description
* A circular detector measuring the radial average of intensity as a function
* of the momentum transform in the sample. The q-range is set up to
* qMax = 4 * PI * sin(TwoThetaMax / 2.0) / LambdaMin;
*
* Example: SAXSQMonitor( RadiusDetector = 0.1, DistanceFromSample = 0.5, LambdaMin = 1, Lambda0 = 1.54, NumberOfBins = 2000 )
* Example: SAXSQMonitor( RadiusDetector = 0.1, qMax = 5, Lambda0 = 1.54, NumberOfBins = 2000 )
*
* %Parameters
* RadiusDetector: [m] Radius of the detector (in the xy-plane).
* DistanceFromSample: [m] Distance from the sample to this component.
* LambdaMin: [AA] Max sensitivity in lambda - used to compute the highest possible value of momentum transfer, q.
* qMax: [Angs-1] Max momentum for the Q-monitor. use either qMax or LambdaMin.
* NumberOfBins: [1] Number of bins in the r (and q).
* RFilename: [str] File used for storing I(r).
* qFilename: [str] File used for storing I(q).
* Lambda0: [Angs] If given, the momentum transfers of all rays are computed from this value. Otherwise, instrumental effects are negated Lambda0=2PI/k.
* restore_xray: [] If set to 1, the component restores the original x-ray.
*
* %End
*******************************************************************************/
DEFINE COMPONENT SAXSQMonitor
SETTING PARAMETERS (string RFilename="RDetectror", string qFilename="QDetector", int NumberOfBins=100, restore_xray=0,
RadiusDetector, DistanceFromSample, LambdaMin = 1.0, Lambda0 = 0.0, qMax=0)
/*X-ray PARAMETERS (x, y, z, kx, ky, kz, phi, t, Ex, Ey, Ez, p)*/
DECLARE
%{
DArray1d Nofq;
DArray1d Iofq;
DArray1d IofqSquared;
DArray1d NofR;
DArray1d IofR;
DArray1d IofRSquared;
%}
INITIALIZE
%{
Nofq=create_darr1d(NumberOfBins);
Iofq=create_darr1d(NumberOfBins);
IofqSquared=create_darr1d(NumberOfBins);
NofR=create_darr1d(NumberOfBins);
IofR=create_darr1d(NumberOfBins);
IofRSquared=create_darr1d(NumberOfBins);
if (DistanceFromSample <= 0)
exit(fprintf(stderr,"%s: ERROR: you must set the DistanceFromSample > 0.\n", NAME_CURRENT_COMP));
if (qMax<=0 && LambdaMin) {
double TwoThetaMax = atan(RadiusDetector / DistanceFromSample);
qMax = 4 * PI * sin(TwoThetaMax / 2.0) / LambdaMin;
}
// Use instance name for monitor output if no input was given
if (!strcmp(RFilename,"\0")) sprintf(RFilename,"%s_R", NAME_CURRENT_COMP);
if (!strcmp(qFilename,"\0")) sprintf(qFilename,"%s_Q", NAME_CURRENT_COMP);
%}
TRACE
%{
int i;
double TwoTheta;
double Lambda;
double R;
double RLow;
double RHigh;
double q;
double qLow;
double qHigh;
double TwoThetaLow;
double TwoThetaHigh;
double AreaOfSlice;
PROP_Z0;
R = sqrt(x*x+y*y);
// Computation of q
if (Lambda0 <= 0.0) {
Lambda = 2.0 * PI / sqrt(kx*kx+ky*ky+kz*kz);
} else {
Lambda = Lambda0;
}
TwoTheta = atan(R / DistanceFromSample);
q = 4.0 * PI * sin(TwoTheta / 2.0) / Lambda;
// Put photon in the correct r-bin
if (R < RadiusDetector) {
i = floor(NumberOfBins * R / RadiusDetector);
RLow = RadiusDetector / NumberOfBins * i;
RHigh = RadiusDetector / NumberOfBins * (i + 1);
TwoThetaLow = atan(RLow / DistanceFromSample);
TwoThetaHigh = atan(RHigh / DistanceFromSample);
AreaOfSlice = fabs((cos(2.0 * TwoThetaLow) - cos(2.0 * TwoThetaHigh)) * 2.0 * PI);
#pragma acc atomic
NofR[i] = NofR[i] + 1;
double p_A=p/AreaOfSlice;
#pragma acc atomic
IofR[i] += p_A;
double p2_A2= p*p/(AreaOfSlice*AreaOfSlice);
#pragma acc atomic
IofRSquared[i] += p2_A2;
}
// Put photon in the correct q-bin
if (q < qMax) {
i = floor(NumberOfBins * q / qMax);
qLow = qMax / NumberOfBins * i;
qHigh = qMax / NumberOfBins * (i + 1);
TwoThetaLow = asin(qLow * Lambda / (4.0 * PI));
TwoThetaHigh = asin(qHigh * Lambda / (4.0 * PI));
AreaOfSlice = fabs((cos(2.0 * TwoThetaLow) - cos(2.0 * TwoThetaHigh)) * 2.0 * PI);
#pragma acc atomic
Nofq[i] = Nofq[i] + 1;
double p_A=p/AreaOfSlice;
#pragma acc atomic
Iofq[i] += p_A;
double p2_A2= p*p/(AreaOfSlice*AreaOfSlice);
#pragma acc atomic
IofqSquared[i] += p2_A2;
SCATTER;
}
// Restore xray if requested
if (restore_xray) {
RESTORE_XRAY(INDEX_CURRENT_COMP, x, y, z, kx, ky, kz, phi, t, Ex, Ey, Ez, p);
}
%}
SAVE
%{
// Output I(r)
DETECTOR_OUT_1D(
"QMonitor - Radially averaged distribution",
"Radius [m]",
"I(r)",
"r",
0.0,
RadiusDetector,
NumberOfBins,
NofR,
IofR,
IofRSquared,
RFilename
);
// Output I(q)
char fname1[256];
snprintf(fname1, 256, "%s_q", NAME_CURRENT_COMP);
// we use mcdetector_out_nD in order to update the [comp_name]_I symbol for the 2nd output
mcdetector_out_1D(
"QMonitor - Distribution in q (Radially averaged)",
"q [1 / AA]",
"I(q)",
"q",
0.0,
qMax,
NumberOfBins,
Nofq,
Iofq,
IofqSquared,
qFilename, fname1,POS_A_CURRENT_COMP,ROT_A_CURRENT_COMP
);
%}
FINALLY
%{
destroy_darr1d(Nofq);
destroy_darr1d(Iofq);
destroy_darr1d(IofqSquared);
destroy_darr1d(NofR);
destroy_darr1d(IofR);
destroy_darr1d(IofRSquared);
%}
MCDISPLAY
%{
circle("xy", 0, 0, 0, RadiusDetector);
%}
END
|