source: sasview/sansmodels/src/c_models/refl_adv.cpp @ ccb7363

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since ccb7363 was dd60b45, checked in by Mathieu Doucet <doucetm@…>, 13 years ago

refl_adv model refactor

  • Property mode set to 100644
File size: 9.9 KB
Line 
1
2#include <math.h>
3#include "parameters.hh"
4#include <stdio.h>
5#include <stdlib.h>
6#include "refl_adv.h"
7
8extern "C" {
9#include "libmultifunc/librefl.h"
10}
11
12using namespace std;
13
14#define lamda 4.62
15
16
17double re_adv_kernel(double dp[], double q) {
18  int n = dp[0];
19  int i,j;
20  double nsl;
21
22  double scale = dp[1];
23  double thick_inter_sub = dp[2];
24  double sld_sub = dp[4];
25  double sld_super = dp[5];
26  double background = dp[6];
27  double npts = dp[69]; //number of sub_layers in each interface
28
29  double total_thick=0.0;
30
31  int n_s;
32  double sld_i,sldim_i,dz,phi,R,ko2;
33  double pi;
34
35  int* fun_type;
36  double* sld;
37  double* sld_im;
38  double* thick_inter;
39  double* thick;
40  double* fun_coef;
41  complex  phi1,alpha,alpha2,kn,fnm,fnp,rn,Xn,nn,nn2,an,nnp1,one,two,n_sub,n_sup,knp1,Xnp1;
42
43  fun_type = (int*)malloc((n+2)*sizeof(int));
44  sld = (double*)malloc((n+2)*sizeof(double));
45  sld_im = (double*)malloc((n+2)*sizeof(double));
46  thick_inter = (double*)malloc((n+2)*sizeof(double));
47  thick = (double*)malloc((n+2)*sizeof(double));
48  fun_coef = (double*)malloc((n+2)*sizeof(double));
49
50  fun_type[0] = dp[3];
51  fun_coef[0] = fabs(dp[70]);
52  for (i =1; i<=n; i++){
53    sld[i] = dp[i+6];
54    thick_inter[i]= dp[i+16];
55    thick[i] = dp[i+26];
56    fun_type[i] = dp[i+36];
57    sld_im[i] = dp[i+46];
58    fun_coef[i] = fabs(dp[i+56]);
59    //printf("type_func2 =%g\n",fun_coef[i]);
60
61    total_thick += thick[i] + thick_inter[i];
62  }
63  sld[0] = sld_sub;
64  sld[n+1] = sld_super;
65  sld_im[0] = fabs(dp[1+66]);
66  sld_im[n+1] = fabs(dp[2+66]);
67  thick[0] = total_thick/5.0;
68  thick[n+1] = total_thick/5.0;
69  thick_inter[0] = thick_inter_sub;
70  thick_inter[n+1] = 0.0;
71  fun_coef[n+1] = 0.0;
72
73  nsl=npts;//21.0; //nsl = Num_sub_layer:  MUST ODD number in double //no other number works now
74
75  pi = 4.0*atan(1.0);
76  one = cassign(1.0,0.0);
77  Xn = cassign(0.0,0.0);
78  two = cassign(0.0,-2.0);
79
80  //Checking if floor is available.
81  //no imaginary sld inputs in this function yet
82  n_sub=cassign(1.0-sld_sub*pow(lamda,2.0)/(2.0*pi),pow(lamda,2.0)/(2.0*pi)*sld_im[0]);
83  n_sup=cassign(1.0-sld_super*pow(lamda,2.0)/(2.0*pi),pow(lamda,2.0)/(2.0*pi)*sld_im[n+1]);
84  ko2 = pow(2.0*pi/lamda,2.0);
85
86  phi = asin(lamda*q/(4.0*pi));
87  phi1 = cplx_div(rcmult(phi,one),n_sup);
88  alpha = cplx_mult(n_sup,cplx_cos(phi1));
89  alpha2 = cplx_mult(alpha,alpha);
90
91  nnp1=n_sub;
92  knp1=cplx_sqrt(rcmult(ko2,cplx_sub(cplx_mult(nnp1,nnp1),alpha2)));  //nnp1*ko*sin(phinp1)
93  Xnp1=cassign(0.0,0.0);
94  dz = 0.0;
95  // iteration for # of layers +sub from the top
96  for (i=1;i<=n+1; i++){
97    //if (fun_coef[i]==0.0)
98    //  // this condition protects an error in numerical multiplication
99    //  fun_coef[i] = 1e-14;
100    //iteration for 9 sub-layers
101    for (j=0;j<2;j++){
102      for (n_s=0;n_s<nsl; n_s++){
103        // for flat layer
104        if (j==1){
105          if (i==n+1)
106            break;
107          dz = thick[i];
108          sld_i = sld[i];
109          sldim_i = sld_im[i];
110        }
111        // for interface
112        else{
113          dz = thick_inter[i-1]/nsl;
114          if (sld[i-1] == sld[i]){
115            sld_i = sld[i];
116          }
117          else{
118            sld_i = intersldfunc(fun_type[i-1],nsl, n_s+0.5, fun_coef[i-1], sld[i-1], sld[i]);
119          }
120          if (sld_im[i-1] == sld_im[i]){
121            sldim_i = sld_im[i];
122          }
123          else{
124            sldim_i = intersldfunc(fun_type[i-1],nsl, n_s+0.5, fun_coef[i-1], sld_im[i-1], sld_im[i]);
125          }
126        }
127        nn = cassign(1.0-sld_i*pow(lamda,2.0)/(2.0*pi),pow(lamda,2.0)/(2.0*pi)*sldim_i);
128        nn2=cplx_mult(nn,nn);
129
130        kn=cplx_sqrt(rcmult(ko2,cplx_sub(nn2,alpha2)));        //nn*ko*sin(phin)
131        an=cplx_exp(rcmult(dz,cplx_mult(two,kn)));
132
133        fnm=cplx_sub(kn,knp1);
134        fnp=cplx_add(kn,knp1);
135        rn=cplx_div(fnm,fnp);
136        Xn=cplx_mult(an,cplx_div(cplx_add(rn,Xnp1),cplx_add(one,cplx_mult(rn,Xnp1))));    //Xn=an*((rn+Xnp1*anp1)/(1+rn*Xnp1*anp1))
137
138        Xnp1=Xn;
139        knp1=kn;
140        // no for-loop for flat layer
141        if (j==1)
142          break;
143      }
144    }
145  }
146  R=pow(Xn.re,2.0)+pow(Xn.im,2.0);
147  // This temperarily fixes the total reflection for Rfunction and linear.
148  // ToDo: Show why it happens that Xn.re=0 and Xn.im >1!
149  if (Xn.im == 0.0 || R > 1){
150    R=1.0;
151  }
152  R *= scale;
153  R += background;
154
155  free(fun_type);
156  free(sld);
157  free(sld_im);
158  free(thick_inter);
159  free(thick);
160  free(fun_coef);
161
162  return R;
163
164}
165ReflAdvModel :: ReflAdvModel() {
166  n_layers = Parameter(1.0);
167  scale = Parameter(1.0);
168  thick_inter0 = Parameter(1.0);
169  func_inter0 = Parameter(0);
170  sld_bottom0 = Parameter(2.07e-06);
171  sld_medium = Parameter(1.0e-06);
172  background = Parameter(0.0);
173
174
175  sld_flat1 = Parameter(2.7e-06);
176  sld_flat2 = Parameter(3.5e-06);
177  sld_flat3 = Parameter(4.0e-06);
178  sld_flat4 = Parameter(3.5e-06);
179  sld_flat5 = Parameter(4.0e-06);
180  sld_flat6 = Parameter(3.5e-06);
181  sld_flat7 = Parameter(4.0e-06);
182  sld_flat8 = Parameter(3.5e-06);
183  sld_flat9 = Parameter(4.0e-06);
184  sld_flat10 = Parameter(3.5e-06);
185
186
187  thick_inter1 = Parameter(1.0);
188  thick_inter2 = Parameter(1.0);
189  thick_inter3 = Parameter(1.0);
190  thick_inter4 = Parameter(1.0);
191  thick_inter5 = Parameter(1.0);
192  thick_inter6 = Parameter(1.0);
193  thick_inter7 = Parameter(1.0);
194  thick_inter8 = Parameter(1.0);
195  thick_inter9 = Parameter(1.0);
196  thick_inter10 = Parameter(1.0);
197
198
199  thick_flat1 = Parameter(15.0);
200  thick_flat2 = Parameter(100.0);
201  thick_flat3 = Parameter(100.0);
202  thick_flat4 = Parameter(100.0);
203  thick_flat5 = Parameter(100.0);
204  thick_flat6 = Parameter(100.0);
205  thick_flat7 = Parameter(100.0);
206  thick_flat8 = Parameter(100.0);
207  thick_flat9 = Parameter(100.0);
208  thick_flat10 = Parameter(100.0);
209
210
211  func_inter1 = Parameter(0);
212  func_inter2 = Parameter(0);
213  func_inter3 = Parameter(0);
214  func_inter4 = Parameter(0);
215  func_inter5 = Parameter(0);
216  func_inter6 = Parameter(0);
217  func_inter7 = Parameter(0);
218  func_inter8 = Parameter(0);
219  func_inter9 = Parameter(0);
220  func_inter10 = Parameter(0);
221
222  sldIM_flat1 = Parameter(0);
223  sldIM_flat2 = Parameter(0);
224  sldIM_flat3 = Parameter(0);
225  sldIM_flat4 = Parameter(0);
226  sldIM_flat5 = Parameter(0);
227  sldIM_flat6 = Parameter(0);
228  sldIM_flat7 = Parameter(0);
229  sldIM_flat8 = Parameter(0);
230  sldIM_flat9 = Parameter(0);
231  sldIM_flat10 = Parameter(0);
232
233  nu_inter1 = Parameter(2.5);
234  nu_inter2 = Parameter(2.5);
235  nu_inter3 = Parameter(2.5);
236  nu_inter4 = Parameter(2.5);
237  nu_inter5 = Parameter(2.5);
238  nu_inter6 = Parameter(2.5);
239  nu_inter7 = Parameter(2.5);
240  nu_inter8 = Parameter(2.5);
241  nu_inter9 = Parameter(2.5);
242  nu_inter10 = Parameter(2.5);
243
244  sldIM_sub0 = Parameter(0.0);
245  sldIM_medium = Parameter(0.0);
246  npts_inter = Parameter(21.0);
247  nu_inter0 = Parameter(2.5);
248}
249
250/**
251 * Function to evaluate 1D NR function
252 * @param q: q-value
253 * @return: function value
254 */
255double ReflAdvModel :: operator()(double q) {
256  double dp[71];
257  // Fill parameter array for IGOR library
258  // Add the background after averaging
259  dp[0] = n_layers();
260  dp[1] = scale();
261  dp[2] = thick_inter0();
262  dp[3] = func_inter0();
263  dp[4] = sld_bottom0();
264  dp[5] = sld_medium();
265  dp[6] = background();
266
267  dp[7] = sld_flat1();
268  dp[8] = sld_flat2();
269  dp[9] = sld_flat3();
270  dp[10] = sld_flat4();
271  dp[11] = sld_flat5();
272  dp[12] = sld_flat6();
273  dp[13] = sld_flat7();
274  dp[14] = sld_flat8();
275  dp[15] = sld_flat9();
276  dp[16] = sld_flat10();
277
278  dp[17] = thick_inter1();
279  dp[18] = thick_inter2();
280  dp[19] = thick_inter3();
281  dp[20] = thick_inter4();
282  dp[21] = thick_inter5();
283  dp[22] = thick_inter6();
284  dp[23] = thick_inter7();
285  dp[24] = thick_inter8();
286  dp[25] = thick_inter9();
287  dp[26] = thick_inter10();
288
289  dp[27] = thick_flat1();
290  dp[28] = thick_flat2();
291  dp[29] = thick_flat3();
292  dp[30] = thick_flat4();
293  dp[31] = thick_flat5();
294  dp[32] = thick_flat6();
295  dp[33] = thick_flat7();
296  dp[34] = thick_flat8();
297  dp[35] = thick_flat9();
298  dp[36] = thick_flat10();
299
300  dp[37] = func_inter1();
301  dp[38] = func_inter2();
302  dp[39] = func_inter3();
303  dp[40] = func_inter4();
304  dp[41] = func_inter5();
305  dp[42] = func_inter6();
306  dp[43] = func_inter7();
307  dp[44] = func_inter8();
308  dp[45] = func_inter9();
309  dp[46] = func_inter10();
310
311  dp[47] = sldIM_flat1();
312  dp[48] = sldIM_flat2();
313  dp[49] = sldIM_flat3();
314  dp[50] = sldIM_flat4();
315  dp[51] = sldIM_flat5();
316  dp[52] = sldIM_flat6();
317  dp[53] = sldIM_flat7();
318  dp[54] = sldIM_flat8();
319  dp[55] = sldIM_flat9();
320  dp[56] = sldIM_flat10();
321
322  dp[57] = nu_inter1();
323  dp[58] = nu_inter2();
324  dp[59] = nu_inter3();
325  dp[60] = nu_inter4();
326  dp[61] = nu_inter5();
327  dp[62] = nu_inter6();
328  dp[63] = nu_inter7();
329  dp[64] = nu_inter8();
330  dp[65] = nu_inter9();
331  dp[66] = nu_inter10();
332
333  dp[67] = sldIM_sub0();
334  dp[68] = sldIM_medium();
335  dp[69] = npts_inter();
336  dp[70] = nu_inter0();
337  // Get the dispersion points for the radius
338  //vector<WeightPoint> weights_thick;
339  //thick_inter0.get_weights(weights_thick_inter0);
340
341
342  return re_adv_kernel(dp,q);
343}
344
345/**
346 * Function to evaluate 2D NR function
347 * @param q_x: value of Q along x
348 * @param q_y: value of Q along y
349 * @return: function value
350 */
351double ReflAdvModel :: operator()(double qx, double qy) {
352  // For 2D set qy as q, ignoring qx.
353  double q = qy;//sqrt(qx*qx + qy*qy);
354  if (q < 0.0){
355    return 0.0;
356  }
357  return (*this).operator()(q);
358}
359
360/**
361 * Function to evaluate 2D NR function
362 * @param pars: parameters of the sphere
363 * @param q: q-value
364 * @param phi: angle phi
365 * @return: function value
366 */
367double ReflAdvModel :: evaluate_rphi(double q, double phi) {
368  return (*this).operator()(q);
369}
370
371/**
372 * Function to calculate effective radius
373 * @return: effective radius value
374 */
375double ReflAdvModel :: calculate_ER() {
376  //NOT implemented yet!!!
377  return 0.0;
378}
Note: See TracBrowser for help on using the repository browser.