Skip to content

Commit 1c5cd21

Browse files
committed
Update Phonon_simple fixing and modernising
Make sure that vf_list has length of 100 and allow the user to choose the amount of scan steps actually taken, if they need to optimise the instrument. This counteracts overflow of vf_list. Also change from parms array to parms struct in order to improve readability.
1 parent 7fbf298 commit 1c5cd21

1 file changed

Lines changed: 103 additions & 62 deletions

File tree

mcstas-comps/samples/Phonon_simple.comp

Lines changed: 103 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@
6666
DEFINE COMPONENT Phonon_simple
6767

6868
SETTING 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) */
7274
SHARE
@@ -75,6 +77,24 @@ SHARE
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
7999
double 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
%}
333366
INITIALIZE
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

465506
MCDISPLAY

0 commit comments

Comments
 (0)