source: sasmodels/sasmodels/models/spherical_sld.c @ eb97b11

core_shell_microgelscostrafo411magnetic_modelrelease_v0.94release_v0.95ticket-1257-vesicle-productticket_1156ticket_1265_superballticket_822_more_unit_tests
Last change on this file since eb97b11 was eb97b11, checked in by wojciech, 8 years ago

Profile function clean-up

  • Property mode set to 100644
File size: 7.4 KB
Line 
1//Headers
2static double form_volume(double thick_inter[],
3    double thick_flat_[],
4    double core_radius,
5    int n_shells);
6
7static double Iq(double q,
8    int n_shells,
9    double thick_inter[],
10    double func_inter[],
11    double sld_core,
12    double sld_solvent,
13    double sld_flat[],
14    double thick_flat[],
15    double nu_inter[],
16    int npts_inter,
17    double core_radius);
18
19static double Iqxy(double qx, double qy,
20    int n_shells,
21    double thick_inter[],
22    double func_inter[],
23    double sld_core,
24    double sld_solvent,
25    double sld_flat[],
26    double thick_flat[],
27    double nu_inter[],
28    int npts_inter,
29    double core_radius);
30
31//Main code
32static double form_volume(double thick_inter[],
33    double thick_flat_[],
34    double core_radius,
35    int n)
36{
37    double radius = 0.0;
38    int i;
39    double r = core_radius;
40    for (i=0; i < n; i++) {
41        r += thick_inter[i];
42        r += thick_flat[i];
43    }
44    return M_4PI_3*cube(r);
45}
46
47
48static double sphere_sld_kernel(double dp[], double q) {
49  int n = dp[0];
50  int i,j,k;
51
52  double scale = dp[1];
53  double thick_inter_core = dp[2];
54  double sld_core = dp[4];
55  double sld_solv = dp[5];
56  double background = dp[6];
57  double npts = dp[57]; //number of sub_layers in each interface
58  double nsl=npts;//21.0; //nsl = Num_sub_layer:  must be ODD double number
59  int n_s;
60
61  double sld_i,sld_f,dz,bes,fun,f,vol,qr,r,contr,f2;
62  double sign,slope=0.0;
63  double pi;
64
65  double total_thick=0.0;
66
67  int fun_type[12];
68  double sld[12];
69  double thick_inter[12];
70  double thick[12];
71  double fun_coef[12];
72
73  fun_type[0] = dp[3];
74  fun_coef[0] = fabs(dp[58]);
75  for (i =1; i<=n; i++){
76    sld[i] = dp[i+6];
77    thick_inter[i]= dp[i+16];
78    thick[i] = dp[i+26];
79    fun_type[i] = dp[i+36];
80    fun_coef[i] = fabs(dp[i+46]);
81    total_thick += thick[i];
82    total_thick += thick_inter[i];
83  }
84  sld[0] = sld_core;
85  sld[n+1] = sld_solv;
86  thick[0] = dp[59];
87  thick[n+1] = total_thick/5.0;
88  thick_inter[0] = thick_inter_core;
89  thick_inter[n+1] = 0.0;
90  fun_coef[n+1] = 0.0;
91  pi = 4.0*atan(1.0);
92  f = 0.0;
93  r = 0.0;
94  vol = 0.0;
95  //vol_pre = 0.0;
96  //vol_sub = 0.0;
97  sld_f = sld_core;
98
99  //floor_nsl = floor(nsl/2.0);
100
101  dz = 0.0;
102  // iteration for # of shells + core + solvent
103  for (i=0;i<=n+1; i++){
104    //iteration for N sub-layers
105    //if (fabs(thick[i]) <= 1e-24){
106    //   continue;
107    //}
108    // iteration for flat and interface
109    for (j=0;j<2;j++){
110      // iteration for sub_shells in the interface
111      // starts from #1 sub-layer
112      for (n_s=1;n_s<=nsl; n_s++){
113        // for solvent, it doesn't have an interface
114        if (i==n+1 && j==1)
115          break;
116        // for flat layers
117        if (j==0){
118          dz = thick[i];
119          sld_i = sld[i];
120          slope = 0.0;
121        }
122        // for interfacial sub_shells
123        else{
124          dz = thick_inter[i]/nsl;
125          // find sld_i at the outer boundary of sub-layer #n_s
126          sld_i = intersldfunc(fun_type[i],nsl, n_s, fun_coef[i], sld[i], sld[i+1]);
127          // calculate slope
128          slope= (sld_i -sld_f)/dz;
129        }
130        contr = sld_f-slope*r;
131        // iteration for the left and right boundary of the shells(or sub_shells)
132        for (k=0; k<2; k++){
133          // At r=0, the contribution to I is zero, so skip it.
134          if ( i == 0 && j == 0 && k == 0){
135            continue;
136          }
137          // On the top of slovent there is no interface; skip it.
138          if (i == n+1 && k == 1){
139            continue;
140          }
141          // At the right side (outer) boundary
142          if ( k == 1){
143            sign = 1.0;
144            r += dz;
145          }
146          // At the left side (inner) boundary
147          else{
148            sign = -1.0;
149          }
150          qr = q * r;
151          fun = 0.0;
152
153          if(qr == 0.0){
154            // sigular point
155            bes = sign * 1.0;
156          }
157          else{
158            // for flat sub-layer
159            //TODO: Single precision calculation most likely fails here
160            //bes = sign *  3.0 * (sin(qr) - qr * cos(qr)) / (qr * qr * qr);
161            bes = sign *  sph_j1c(qr);
162            if (fabs(slope) > 0.0 ){
163              //fun = sign * 3.0 * r * (2.0*qr*sin(qr)-((qr*qr)-2.0)*cos(qr))/(qr * qr * qr * qr);
164              fun = sign * r * sph_j1c(qr) + sign * 3.0 * sin(qr)/(qr * qr * q )
165                + sign * 6.0 * cos(qr)/(qr * qr * qr * q);
166            }
167          }
168
169          //Some initial optimization tries
170          /*bes = (qr == 0.0 ? sign * 1.0 : sign *  3.0 * (sin(qr) - qr * cos(qr)) / (qr * qr * qr));
171          //TODO: Will have to chnage this function
172          if (qr!= 0.0 && fabs(slope) > 0.0 ){
173            fun = sign * 3.0 * r * (2.0*qr*sin(qr)-((qr*qr)-2.0)*cos(qr))/(qr * qr * qr * qr);
174          }*/
175
176          // update total volume
177          vol = 4.0 * pi / 3.0 * r * r * r;
178          // we won't do the following volume correction for now.
179          // substrate empty area of volume
180          //if (k == 1 && fabs(sld_in[i]-sld_solv) < 1e-04*fabs(sld_solv) && fun_type[i]==0){
181          //  vol_sub += (vol_pre - vol);
182          //}
183          f += vol * (bes * contr + fun * slope);
184        }
185        // remember this sld as sld_f
186        sld_f = sld_i;
187        // no sub-layer iteration (n_s loop) for the flat layer
188        if (j==0)
189          break;
190      }
191    }
192  }
193  //vol += vol_sub;
194  f2 = f * f / vol;
195  //f2 *= scale;
196  //f2 += background;
197  //free(fun_type);
198  //free(sld);
199  //free(thick_inter);
200  //free(thick);
201  //free(fun_coef);
202
203  return (f2);
204}
205
206
207/**
208 * Function to evaluate 1D SphereSLD function
209 * @param q: q-value
210 * @return: function value
211 */
212double Iq(double q,
213    int n_shells,
214    double thick_inter[],
215    double func_inter[],
216    double sld_core,
217    double sld_solvent,
218    double sld_flat[],
219    double thick_flat[],
220    double nu_inter[],
221    int npts_inter,
222    double core_radius
223    ) {
224
225    //printf("Number of points %d\n",npts_inter);
226    double intensity;
227    //TODO: Remove this container at later stage. It is only kept to minimize stupid errors now
228    double dp[60];
229    dp[0] = n_shells;
230    //This is scale will also have to be removed at some stage
231    dp[1] = 1.0;
232    dp[2] = thick_inter_0;
233    dp[3] = func_inter_0;
234    dp[4] = sld_core;
235    dp[5] = sld_solvent;
236    dp[6] = 0.0;
237
238    for (i=0; i<n; i++){
239        dp[i+7] = sld_flat[i];
240        dp[i+17] = thick_inter[i];
241        dp[i+27] = thick_flat[i];
242        dp[i+37] = func_inter[i];
243        dp[i+47] = nu_inter[i];
244    }
245
246    dp[57] = npts_inter;
247    dp[58] = nu_inter_0;
248    dp[59] = rad_core_0;
249
250    intensity = 1.0e-4*sphere_sld_kernel(dp,q);
251    //printf("%10d\n",intensity);
252    return intensity;
253}
254
255/**
256 * Function to evaluate 2D SphereSLD function
257 * @param q_x: value of Q along x
258 * @param q_y: value of Q along y
259 * @return: function value
260 */
261double Iqxy(double qx, double qy,
262    int n_shells,
263    double thick_inter[],
264    double func_inter[],
265    double sld_core,
266    double sld_solvent,
267    double sld_flat[],
268    double thick_flat[],
269    double nu_inter[],
270    int npts_inter,
271    double core_radius
272    ) {
273
274    double q = sqrt(qx*qx + qy*qy);
275    return Iq(q, n_shells, thick_inter[], func_inter[], sld_core, sld_solvent,
276    sld_flat[], thick_flat[],nu_inter[], npts_inter, core_radius)
277
278}
279
Note: See TracBrowser for help on using the repository browser.