File: TOFRes_sample.comp

package info (click to toggle)
mccode 3.5.19%2Bds5-2
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 1,113,256 kB
  • sloc: ansic: 40,697; python: 25,137; yacc: 8,438; sh: 5,405; javascript: 4,596; lex: 1,632; cpp: 742; perl: 296; lisp: 273; makefile: 226; fortran: 132
file content (322 lines) | stat: -rw-r--r-- 11,849 bytes parent folder | download
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
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
/*******************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright 1997-2002, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*
* Component: TOFRes_sample
*
* %I
* Modified from Res_sample, written by: Kristian Nielsen
* Date: 1999
* Written by: KL, 10 October 2004
* Modified by KL, 20 March 2024 after input from Ryoichi Kajimoto, J-PARC
* Origin: Risoe
*
* Sample for TOF resolution function calculation.
*
* %D
* An inelastic sample with completely uniform scattering in both solid angle
* and energy. This sample is used together with the TOFRes_monitor component
* and (optionally) the mcresplot front-end to compute the resolution
* function of all time-of-flight instruments.
* The method of time focusing is used to optimize the simulations.
*
* The shape of the sample is either:
* 1. Hollow cylinder (Please note that the cylinder **must** be specified with both 
*    a radius and a wall-thickness!)
* 2. A massive, rectangular box specified with dimensions xwidth, yheight, zdepth.
*    (i.e. **withouht** a thickness)
*
* hollow cylinder shape **must** be specified with both a radius and a wall-thickness.
* The box is 
*
* The scattered neutrons will have directions towards a given target and
* detector arrival time in an interval of time_width centered on time_bin.
* This target area is default disk shaped, but may also be rectangular
* if specified focus_xw and focus_yh
* or focus_aw and focus_ah, respectively in meters and degrees.
* The target itself is either situated according to given coordinates (x,y,z),
* or setting the relative target_index of the component to focus at
* (next is +1). This target position will be set to its AT position.
* When targeting to centered components, such as spheres or cylinders,
* define an Arm component where to focus at.
*
* Example: TOFRes_sample(thickness=0.001, radius=0.01, yheight=0.04, focus_xw=0.025, focus_yh=0.025, time_bin=3e4, time_width=200, target_x=0, target_y=0, target_z=1)
*
* %P
* INPUT PARAMETERS:
*
* thickness: [m]     Thickness of hollow cylinder in (x,z) plane 
* radius: [m]        Outer radius of hollow cylinder 
* yheight: [m]       vert.  dimension of sample, as a height 
* focus_r: [m]       Radius of sphere containing target 
* target_index: [1]  relative index of component to focus at, e.g. next is +1 
* time_bin: [us]     position of time bin 
* time_width: [us]   width of time bin 
* f: [1]             Adaptive time-shortening factor
*
* Optional parameters
* xwidth: [m]        horiz. dimension of sample, as a width 
* zdepth: [m]        depth of sample 
* focus_xw: [m]      horiz. dimension of a rectangular area 
* focus_yh: [m]      vert.  dimension of a rectangular area 
* focus_aw: [deg]    horiz. angular dimension of a rectangular area 
* focus_ah: [deg]    vert.  angular dimension of a rectangular area 
* target_x: []       
* target_y: [m]      position of target to focus at 
* target_z: []       
* %E
*******************************************************************************/

DEFINE COMPONENT TOFRes_sample



SETTING PARAMETERS (thickness=0,radius=0.01,yheight=0.05,focus_r=0.05,
time_bin=20000, time_width=10, f=50,
target_x=0, target_y=0, target_z=.5, focus_xw=0, focus_yh=0,
focus_aw=0, focus_ah=0, xwidth=0, zdepth=0, int target_index=0)

/* Neutron parameters: (x,y,z,vx,vy,vz,t,sx,sy,sz,p) */

SHARE
%{
  struct Res_sample_struct {
    char   isrect;      /* true when7 sample is a box */
    double distance;    /* when non zero, gives rect target distance */
    double aw,ah;       /* rectangular angular dimensions */
    double xw,yh;       /* rectangular metrical dimensions */
    double tx,ty,tz;    /* target coords */
  };
%}

/* Needed for resolution calculation */
USERVARS %{
  double res_pi;
  double res_ki_x;
  double res_ki_y;
  double res_ki_z;
  double res_kf_x;
  double res_kf_y;
  double res_kf_z;
  double res_rx;
  double res_ry;
  double res_rz;
%}

DECLARE
%{
  struct Res_sample_struct res_struct;
  char res_pi_var[20];
  char res_ki_x_var[20];
  char res_ki_y_var[20];
  char res_ki_z_var[20];
  char res_kf_x_var[20];
  char res_kf_y_var[20];
  char res_kf_z_var[20];
  char res_rx_var[20];
  char res_ry_var[20];
  char res_rz_var[20];
  int compindex;
%}

INITIALIZE
%{

if (!radius || !yheight) {
  if (!xwidth || !yheight || !zdepth) {
    exit(fprintf(stderr,"TOFRes_sample: %s: box-shaped sample has no volume (zero dimensions)\n", NAME_CURRENT_COMP));
  } else {
    res_struct.isrect=1;
  }
 } else {
  res_struct.isrect=0;
  if (!thickness || thickness >= radius) {
    exit(fprintf(stderr,"TOFRes_sample: %s: Hollow of cylindrical sample has no volume (zero dimensions)\n", NAME_CURRENT_COMP));
  }
 }
 
  /* now compute target coords if a component index is supplied */
  if (target_index)
  {
    Coords ToTarget;
    ToTarget = coords_sub(POS_A_COMP_INDEX(INDEX_CURRENT_COMP+target_index),POS_A_CURRENT_COMP);
    ToTarget = rot_apply(ROT_A_CURRENT_COMP, ToTarget);
    coords_get(ToTarget, &res_struct.tx, &res_struct.ty, &res_struct.tz);
  }
  else
  { res_struct.tx = target_x; res_struct.ty = target_y; res_struct.tz = target_z; }

  res_struct.distance=sqrt(res_struct.tx*res_struct.tx
      +res_struct.ty*res_struct.ty+res_struct.tz*res_struct.tz);
  /* different ways of setting rectangular area */
  res_struct.aw  = res_struct.ah = 0;
  if (focus_xw) {
    res_struct.xw = focus_xw;
  }
  if (focus_yh) {
    res_struct.yh = focus_yh;
  }
  if (focus_aw) {
    res_struct.aw = DEG2RAD*focus_aw;
  }
  if (focus_ah) {
    res_struct.ah = DEG2RAD*focus_ah;
  }

  /* Initialize uservar strings */
  sprintf(res_pi_var,"res_pi_%i",_comp->_index);
  sprintf(res_ki_x_var,"res_ki_x_%i",_comp->_index);
  sprintf(res_ki_y_var,"res_ki_y_%i",_comp->_index);
  sprintf(res_ki_z_var,"res_ki_z_%i",_comp->_index);
  sprintf(res_kf_x_var,"res_kf_x_%i",_comp->_index);
  sprintf(res_kf_y_var,"res_kf_y_%i",_comp->_index);
  sprintf(res_kf_z_var,"res_kf_z_%i",_comp->_index);
  sprintf(res_rx_var,"res_rx_%i",_comp->_index);
  sprintf(res_ry_var,"res_ry_%i",_comp->_index);
  sprintf(res_rz_var,"res_rz_%i",_comp->_index);
  compindex=_comp->_index;
  
%}

TRACE
%{
  double t0, t3;                /* Entry/exit time for outer cylinder */
  double t1, t2;                /* Entry/exit time for inner cylinder */
  double v;                     /* Neutron velocity */
  double E;
  double l_full;                /* Flight path length for non-scattered neutron */
  double flight_time;           /* Calculated time-of-flight from source to target (detector) */
  double dt0, dt1, dt2, dt;     /* Flight times through sample */
  double solid_angle=0;         /* Solid angle of target as seen from scattering point */
  double aim_x, aim_y, aim_z, aim_length;
                                /* Position of target relative to scattering point */
  double norm_factor;           /* Normalization factor */
  int    intersect=0;
  double kix,kiy,kiz;
  double kfx,kfy,kfz;

  if(res_struct.isrect)
    intersect = box_intersect(&t0, &t3, x, y, z, vx, vy, vz, xwidth, yheight, zdepth);
  else
    intersect = cylinder_intersect(&t0, &t3, x, y, z, vx, vy, vz, radius, yheight);

  if(intersect)
  {
    if(t0 < 0) ABSORB;
    if(res_struct.isrect) { t1 = t2 = t3; norm_factor = 2*zdepth; } /* box sample */
    else {
      /* Cylindrical sample */
      /* Neutron enters at t=t0. */
      /* If cylinder hollow does not exist or is NOT intersected */ 
      if(thickness==0 || !cylinder_intersect(&t1, &t2, x, y, z, vx, vy, vz, radius-thickness, yheight)) {
        t1 = t2 = t3;
      } else {
	ABSORB;
      }
      norm_factor = 2*thickness;  /* Maximum path length in the sample for zero vertical divergence */
    }
    dt0 = t1-t0;                  /* Time in sample, ingoing */
    dt1 = t2-t1;                  /* Time in hole */
    dt2 = t3-t2;                  /* Time in sample, outgoing */
    v = sqrt(vx*vx + vy*vy + vz*vz);
    l_full = v * (dt0 + dt2);     /* Length of full path through sample */
    p *= l_full/norm_factor;      /* Normalized scattering probability, proportional to path length in the sample */
    dt = rand01()*(dt0+dt2);      /* Time of scattering (relative to t0) */
    if (dt > dt0)
      dt += dt1;

    PROP_DT(dt+t0);             /* Point of scattering */

    /* Store initial neutron state. */
    if(p == 0) ABSORB;
    kix=V2K*vx; kiy=V2K*vy; kiz=V2K*vz;
    particle_setvar_void(_particle, res_pi_var, &p);
    particle_setvar_void(_particle, res_ki_x_var, &(kix));
    particle_setvar_void(_particle, res_ki_y_var, &(kiy));
    particle_setvar_void(_particle, res_ki_z_var, &(kiz));
    particle_setvar_void(_particle, res_rx_var, &x);
    particle_setvar_void(_particle, res_ry_var, &y);
    particle_setvar_void(_particle, res_rz_var, &z);

    aim_x = res_struct.tx-x;       /* Vector pointing at target (anal./det.) */
    aim_y = res_struct.ty-y;
    aim_z = res_struct.tz-z;
    aim_length = sqrt(aim_x*aim_x+aim_y*aim_y+aim_z*aim_z);
    if(res_struct.aw && res_struct.ah) {
      randvec_target_rect_angular(&vx, &vy, &vz, &solid_angle,
        aim_x, aim_y, aim_z, res_struct.aw, res_struct.ah, ROT_A_CURRENT_COMP);
    } else if(res_struct.xw && res_struct.yh) {
      randvec_target_rect(&vx, &vy, &vz, &solid_angle,
        aim_x, aim_y, aim_z, res_struct.xw, res_struct.yh, ROT_A_CURRENT_COMP);
    } else {
        randvec_target_circle(&vx, &vy, &vz, &solid_angle,
          aim_x, aim_y, aim_z, focus_r);
    }
    NORM(vx, vy, vz);
    flight_time = -t + 1e-6*(time_bin + time_width * randpm1());
    /* Correct for too large or negative flight_times, based on user-defined f */
    for (; flight_time<0; flight_time += 1/f);
    for (; flight_time>1/f; flight_time -= 1/f);
    v = aim_length / flight_time;
    /* !! Remember later to correct for Jacobian in MC choice, t to V !! */

    vx *= v;
    vy *= v;
    vz *= v;
    SCATTER;

    /* Store final neutron state. */
    kfx=V2K*vx; kfy=V2K*vy; kfz=V2K*vz;
    particle_setvar_void(_particle, res_kf_x_var, &(kfx));
    particle_setvar_void(_particle, res_kf_y_var, &(kfy));
    particle_setvar_void(_particle, res_kf_z_var, &(kfz));
  }
%}

MCDISPLAY
%{
  
  if(res_struct.isrect)
  {                             /* Flat sample. */
    double xmin = -0.5*xwidth;
    double xmax =  0.5*xwidth;
    double ymin = -0.5*yheight;
    double ymax =  0.5*yheight;
    double len = zdepth/2;
    multiline(5, xmin, ymin, -len,
                 xmax, ymin, -len,
                 xmax, ymax, -len,
                 xmin, ymax, -len,
                 xmin, ymin, -len);
    multiline(5, xmin, ymin, len,
                 xmax, ymin, len,
                 xmax, ymax, len,
                 xmin, ymax, len,
                 xmin, ymin, len);
    line(xmin, ymin, -len, xmin, ymin, len);
    line(xmax, ymin, -len, xmax, ymin, len);
    line(xmin, ymax, -len, xmin, ymax, len);
    line(xmax, ymax, -len, xmax, ymax, len);
  }
  else
  {
    double radius_i = thickness ? radius-thickness : 0;
    circle("xz", 0,  yheight/2.0, 0, radius_i);
    circle("xz", 0,  yheight/2.0, 0, radius);
    circle("xz", 0, -yheight/2.0, 0, radius_i);
    circle("xz", 0, -yheight/2.0, 0, radius);
    line(-radius_i, -yheight/2.0, 0, -radius_i, +yheight/2.0, 0);
    line(+radius_i, -yheight/2.0, 0, +radius_i, +yheight/2.0, 0);
    line(0, -yheight/2.0, -radius_i, 0, +yheight/2.0, -radius_i);
    line(0, -yheight/2.0, +radius_i, 0, +yheight/2.0, +radius_i);
    line(-radius, -yheight/2.0, 0, -radius, +yheight/2.0, 0);
    line(+radius, -yheight/2.0, 0, +radius, +yheight/2.0, 0);
    line(0, -yheight/2.0, -radius, 0, +yheight/2.0, -radius);
    line(0, -yheight/2.0, +radius, 0, +yheight/2.0, +radius);
  }
%}

END