6666DEFINE COMPONENT Phonon_simple
6767
6868SETTING PARAMETERS (radius,yheight,sigma_abs,sigma_inc,a,b,M,c,DW,T,
69- target_x=0, target_y=0, target_z=0, int target_index=0,focus_r=0,focus_xw=0,focus_yh=0,focus_aw=0,focus_ah=0, gap=0)
69+ target_x=0, target_y=0, target_z=0, int target_index=0,
70+ focus_r=0,focus_xw=0,focus_yh=0,focus_aw=0,focus_ah=0,
71+ gap=0, int e_steps_low=50, int e_steps_high=50)
7072
7173/* Neutron parameters: (x,y,z,vx,vy,vz,t,sx,sy,sz,p) */
7274SHARE
7577#define PHONON_SIMPLE $Revision$
7678#define T2E (1/11.605) /* Kelvin to meV */
7779
80+ struct neutron_and_phonon_params {
81+ // Statically allocate vectors that are always 3
82+ double vf; // Final velocity size
83+ double vi; // Initial velocity size
84+ double vv_x; // vv is the unit vector of the final velocity vector
85+ double vv_y;
86+ double vv_z;
87+ double vi_x; // vi is the initial velocity vector
88+ double vi_y;
89+ double vi_z;
90+ double a_; // d spacing of the cubic lattice
91+ double c_; // Speed of sound in the material
92+ double gap_; // optional spin gap
93+ double ah; // Half of a
94+ int e_steps_high_;
95+ int e_steps_low_;
96+ };
97+
7898#pragma acc routine
7999double nbose(double omega, double T) /* Other name ?? */
80100 {
@@ -103,26 +123,26 @@ void fatalerror(char *s)
103123 }
104124
105125 #pragma acc routine
106- double omega_q(double* parms)
126+ double omega_q(struct neutron_and_phonon_params * parms)
107127 {
108128 /* dispersion in units of meV */
109129 double vi, vf, vv_x, vv_y, vv_z, vi_x, vi_y, vi_z;
110130 double q, qx, qy, qz, Jq, res_phonon, res_neutron;
111131 double ah, a, c;
112132 double gap;
113133
114- vf=parms[0] ;
115- vi=parms[1] ;
116- vv_x=parms[2] ;
117- vv_y=parms[3] ;
118- vv_z=parms[4] ;
119- vi_x=parms[5] ;
120- vi_y=parms[6] ;
121- vi_z=parms[7] ;
122- a =parms[8] ;
123- c =parms[9] ;
124- gap =parms[10] ;
125- ah=a/2.0 ;
134+ vf=parms->vf ;
135+ vi=parms->vi ;
136+ vv_x=parms->vv_x ;
137+ vv_y=parms->vv_y ;
138+ vv_z=parms->vv_z ;
139+ vi_x=parms->vi_x ;
140+ vi_y=parms->vi_y ;
141+ vi_z=parms->vi_z ;
142+ a =parms->a_ ;
143+ c =parms->c_ ;
144+ gap =parms->gap_ ;
145+ ah =parms->ah ;
126146
127147 qx=V2K*(vi_x-vf*vv_x);
128148 qy=V2K*(vi_y-vf*vv_y);
@@ -141,15 +161,15 @@ void fatalerror(char *s)
141161 }
142162
143163
144- double zridd(double (*func)(double *), double x1, double x2, double *parms, double xacc)
164+ double zridd(double (*func)(struct neutron_and_phonon_params *), double x1, double x2, struct neutron_and_phonon_params *parms, double xacc)
145165 {
146166 int j;
147167 double ans, fh, fl, fm, fnew, s, xh, xl, xm, xnew;
148168
149- parms[0] =x1;
150- fl=(* func) (parms);
151- parms[0] =x2;
152- fh=(* func) (parms);
169+ parms->vf =x1;
170+ fl=func(parms);
171+ parms->vf =x2;
172+ fh=func(parms);
153173 if (fl*fh >= 0)
154174 {
155175 if (fl==0) return x1;
@@ -164,17 +184,17 @@ double zridd(double (*func)(double*), double x1, double x2, double *parms, doubl
164184 for (j=1; j<MAXRIDD; j++)
165185 {
166186 xm=0.5*(xl+xh);
167- parms[0] =xm;
168- fm=(* func) (parms);
187+ parms->vf =xm;
188+ fm=func(parms);
169189 s=sqrt(fm*fm-fl*fh);
170190 if (s == 0.0)
171191 return ans;
172192 xnew=xm+(xm-xl)*((fl >= fh ? 1.0 : -1.0)*fm/s);
173193 if (fabs(xnew-ans) <= xacc)
174194 return ans;
175195 ans=xnew;
176- parms[0] =ans;
177- fnew=(* func) (parms);
196+ parms->vf =ans;
197+ fnew=func(parms);
178198 if (fnew == 0.0) return ans;
179199 if (fabs(fm)*SIGN(fnew) != fm)
180200 {
@@ -206,14 +226,14 @@ double zridd(double (*func)(double*), double x1, double x2, double *parms, doubl
206226 }
207227
208228#pragma acc routine
209- double zridd_gpu(double x1, double x2, double *parms, double xacc)
229+ double zridd_gpu(double x1, double x2, struct neutron_and_phonon_params *parms, double xacc)
210230 {
211231 int j;
212232 double ans, fh, fl, fm, fnew, s, xh, xl, xm, xnew;
213233
214- parms[0] =x1;
234+ parms->vf =x1;
215235 fl=omega_q(parms);
216- parms[0] =x2;
236+ parms->vf =x2;
217237 fh=omega_q(parms);
218238 if (fl*fh >= 0)
219239 {
@@ -229,7 +249,7 @@ double zridd_gpu(double x1, double x2, double *parms, double xacc)
229249 for (j=1; j<MAXRIDD; j++)
230250 {
231251 xm=0.5*(xl+xh);
232- parms[0] =xm;
252+ parms->vf =xm;
233253 fm=omega_q(parms);
234254 s=sqrt(fm*fm-fl*fh);
235255 if (s == 0.0)
@@ -238,7 +258,7 @@ double zridd_gpu(double x1, double x2, double *parms, double xacc)
238258 if (fabs(xnew-ans) <= xacc)
239259 return ans;
240260 ans=xnew;
241- parms[0] =ans;
261+ parms->vf =ans;
242262 fnew=omega_q(parms);
243263 if (fnew == 0.0) return ans;
244264 if (fabs(fm)*SIGN(fnew) != fm)
@@ -273,30 +293,40 @@ double zridd_gpu(double x1, double x2, double *parms, double xacc)
273293
274294#define ROOTACC 1e-8
275295
276- int findroots(double brack_low, double brack_mid, double brack_high, double *list, int* index, double (*f)(double*), double *parms)
296+ void findroots(double brack_low, double brack_mid, double brack_high,
297+ double *list, int* index, double (*f)(struct neutron_and_phonon_params*),
298+ struct neutron_and_phonon_params *parms)
277299 {
278- double root,range=brack_mid-brack_low;
279- int i, steps=100;
280-
281- for (i=0; i<steps; i++)
282- {
283- root = zridd(f, brack_low+range*i/(int)steps,
284- brack_low+range*(i+1)/(int)steps,
285- (double *)parms, ROOTACC);
300+ double root;
301+ // Energy gain and energy loss spaces are not equally big. We check uniformly
302+ // So we use two different ranges
303+ double range_low = brack_mid - brack_low;
304+ double range_high = brack_high - brack_mid;
305+ // First in energy loss for the neutron
306+ for (int i=0; i<parms->e_steps_low_; i++){
307+ root = zridd(f, brack_low+range_low*i/ parms->e_steps_low_,
308+ brack_low+range_low*(i+1)/ parms->e_steps_low_,
309+ parms, ROOTACC);
286310 if (root != UNUSED)
287311 {
288312 list[(*index)++]=root;
289313 }
290314 }
291- root = zridd(f, brack_mid, brack_high, (double *)parms, ROOTACC);
292- if (root != UNUSED)
293- {
315+
316+ // Then in energy gain for the neutron
317+ for (int i=0; i<parms->e_steps_high_; i++){
318+ root = zridd(f, brack_low+range_high*i/ parms->e_steps_high_,
319+ brack_low+range_high*(i+1)/ parms->e_steps_high_,
320+ parms, ROOTACC);
321+ if (root != UNUSED){
294322 list[(*index)++]=root;
295323 }
324+ }
296325 }
297326
298327#pragma acc routine
299- int findroots_gpu(double brack_low, double brack_mid, double brack_high, double *list, int* index, double *parms)
328+ void findroots_gpu(double brack_low, double brack_mid, double brack_high,
329+ double *list, int* index, struct neutron_and_phonon_params *parms)
300330 {
301331 double root,range=brack_mid-brack_low;
302332 int i, steps=100;
@@ -305,13 +335,13 @@ double zridd_gpu(double x1, double x2, double *parms, double xacc)
305335 {
306336 root = zridd_gpu(brack_low+range*i/(int)steps,
307337 brack_low+range*(i+1)/(int)steps,
308- (double *) parms, ROOTACC);
338+ parms, ROOTACC);
309339 if (root != UNUSED)
310340 {
311341 list[(*index)++]=root;
312342 }
313343 }
314- root = zridd_gpu(brack_mid, brack_high, (double *) parms, ROOTACC);
344+ root = zridd_gpu(brack_mid, brack_high, parms, ROOTACC);
315345 if (root != UNUSED)
316346 {
317347 list[(*index)++]=root;
@@ -329,13 +359,25 @@ DECLARE
329359 double V_my_s;
330360 double V_my_a_v;
331361 double DV;
362+ double vf_list[100];// List of allowed final velocities. Has length of scan_steps
363+ struct neutron_and_phonon_params parms;
364+
332365%}
333366INITIALIZE
334367%{
368+ memset(vf_list, 0, sizeof(vf_list));
335369 V_rho = 4/(a*a*a);
336370 V_my_s = (V_rho * 100 * sigma_inc);
337371 V_my_a_v = (V_rho * 100 * sigma_abs * 2200);
338372 DV = 0.001; /* Velocity change used for numerical derivative */
373+
374+ // Set constant parameters for parms object
375+ parms.a_ = a;
376+ parms.c_ = c;
377+ parms.gap_ = gap;
378+ parms.ah = a/2.0;
379+ parms.e_steps_high_ = e_steps_high;
380+ parms.e_steps_low_ = e_steps_low;
339381
340382 /* now compute target coords if a component index is supplied */
341383 if (!target_index && !target_x && !target_y && !target_z) target_index=1;
@@ -368,11 +410,9 @@ TRACE
368410 double bose_factor; /* Calculated value of the Bose factor */
369411 double omega; /* energy transfer */
370412 int nf, index; /* Number of allowed final velocities */
371- double vf_list[2]; /* List of allowed final velocities */
372413 double J_factor; /* Jacobian from delta fnc.s in cross section */
373414 double f1, f2; /* probed values of omega_q minus omega */
374415 double p1,p2,p3,p4,p5; /* temporary multipliers */
375- double parms[11];
376416
377417 if(cylinder_intersect(&t0, &t1, x, y, z, vx, vy, vz, radius, yheight))
378418 {
@@ -405,29 +445,27 @@ TRACE
405445 }
406446 NORM(vx, vy, vz);
407447 nf=0;
408- parms[0]=-1;
409- parms[1]=v_i;
410- parms[2]=vx;
411- parms[3]=vy;
412- parms[4]=vz;
413- parms[5]=vx_i;
414- parms[6]=vy_i;
415- parms[7]=vz_i;
416- parms[8]=a;
417- parms[9]=c;
418- parms[10]=gap;
448+ parms.vf = -1;
449+ parms.vi = v_i;
450+ parms.vv_x = vx;
451+ parms.vv_y = vy;
452+ parms.vv_z = vz;
453+ parms.vi_x = vx_i;
454+ parms.vi_y = vy_i;
455+ parms.vi_z = vz_i;
456+
419457 #ifndef OPENACC
420- findroots(0, v_i, v_i+2*c*V2K/VS2E, vf_list, &nf, omega_q, parms);
458+ findroots(0, v_i, v_i+2*c*V2K/VS2E, vf_list, &nf, omega_q, & parms);
421459 #else
422- findroots_gpu(0, v_i, v_i+2*c*V2K/VS2E, vf_list, &nf, parms);
460+ findroots_gpu(0, v_i, v_i+2*c*V2K/VS2E, vf_list, &nf, & parms);
423461 #endif
424462 index=(int)floor(rand01()*nf);
425463 if (index<2) {
426464 v_f=vf_list[index];
427- parms[0] =v_f-DV;
428- f1=omega_q(parms);
429- parms[0] =v_f+DV;
430- f2=omega_q(parms);
465+ parms.vf =v_f-DV;
466+ f1=omega_q(& parms);
467+ parms.vf =v_f+DV;
468+ f2=omega_q(& parms);
431469 J_factor = fabs(f2-f1)/(2*DV);
432470 omega=VS2E*(v_i*v_i-v_f*v_f);
433471 vx *= v_f;
@@ -460,6 +498,9 @@ TRACE
460498 ABSORB; // findroots returned junk
461499 }
462500 } /* else transmit: Neutron did not hit the sample */
501+
502+ // Finally, set vf_list to zero again
503+ memset(vf_list, 0, nf * sizeof(double));
463504%}
464505
465506MCDISPLAY
0 commit comments