source: sasview/sansmodels/src/sans/models/libigor/libCylinder.c @ feadd6f

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 feadd6f was 5f0dcab, checked in by Mathieu Doucet <doucetm@…>, 13 years ago

Re #4 Get rid of warnings by putting static and defs in the right place.

  • Property mode set to 100644
File size: 80.4 KB
Line 
1/*      CylinderFit.c
2
3A simplified project designed to act as a template for your curve fitting function.
4The fitting function is a Cylinder form factor. No resolution effects are included (yet)
5*/
6
7#include "StandardHeaders.h"                    // Include ANSI headers, Mac headers
8#include "GaussWeights.h"
9#include "libCylinder.h"
10
11/////////functions for WRC implementation of flexible cylinders
12static double
13gammaln(double xx)
14{
15  double x,y,tmp,ser;
16  static double cof[6]={76.18009172947146,-86.50532032941677,
17    24.01409824083091,-1.231739572450155,
18    0.1208650973866179e-2,-0.5395239384953e-5};
19  int j;
20
21  y=x=xx;
22  tmp=x+5.5;
23  tmp -= (x+0.5)*log(tmp);
24  ser=1.000000000190015;
25  for (j=0;j<=5;j++) ser += cof[j]/++y;
26  return -tmp+log(2.5066282746310005*ser/x);
27}
28/////////functions for WRC implementation of flexible cylinders
29
30//
31static double
32AlphaSquare(double x)
33{
34    double yy;
35    yy = pow( (1.0 + (x/3.12)*(x/3.12) + (x/8.67)*(x/8.67)*(x/8.67)),(0.176/3.0) );
36
37    return (yy);
38}
39
40//
41static double
42Rgsquarezero(double q, double L, double b)
43{
44    double yy;
45    yy = (L*b/6.0) * (1.0 - 1.5*(b/L) + 1.5*pow((b/L),2) - 0.75*pow((b/L),3)*(1.0 - exp(-2.0*(L/b))));
46
47    return (yy);
48}
49
50//
51static double
52Rgsquareshort(double q, double L, double b)
53{
54    double yy;
55    yy = AlphaSquare(L/b) * Rgsquarezero(q,L,b);
56
57    return (yy);
58}
59
60//
61static double
62Rgsquare(double q, double L, double b)
63{
64    double yy;
65    yy = AlphaSquare(L/b)*L*b/6.0;
66
67    return (yy);
68}
69
70// ?? funciton is not used - but should the log actually be log10???
71static double
72miu(double x)
73{
74    double yy;
75    yy = (1.0/8.0)*(9.0*x - 2.0 + 2.0*log(1.0 + x)/x)*exp(1.0/2.565*(1.0/x + (1.0 - 1.0/(x*x))*log(1.0 + x)));
76
77    return (yy);
78}
79
80//WR named this w (too generic)
81static double
82w_WR(double x)
83{
84    double yy;
85    yy = 0.5*(1 + tanh((x - 1.523)/0.1477));
86
87    return (yy);
88}
89
90//
91static double
92u1(double q, double L, double b)
93{
94    double yy;
95
96    yy = Rgsquareshort(q,L,b)*q*q;
97
98    return (yy);
99}
100
101// was named u
102static double
103u_WR(double q, double L, double b)
104{
105    double yy;
106    yy = Rgsquare(q,L,b)*q*q;
107    return (yy);
108}
109
110
111//
112static double
113Sdebye1(double q, double L, double b)
114{
115    double yy;
116    yy = 2.0*(exp(-u1(q,L,b)) + u1(q,L,b) -1.0)/( pow((u1(q,L,b)),2.0) );
117
118    return (yy);
119}
120
121
122//
123static double
124Sdebye(double q, double L, double b)
125{
126    double yy;
127    yy = 2.0*(exp(-u_WR(q,L,b)) + u_WR(q,L,b) -1.0)/(pow((u_WR(q,L,b)),2));
128
129    return (yy);
130}
131
132//
133static double
134Sexv(double q, double L, double b)
135{
136    double yy,C1,C2,C3,miu,Rg2;
137    C1=1.22;
138    C2=0.4288;
139    C3=-1.651;
140    miu = 0.585;
141
142    Rg2 = Rgsquare(q,L,b);
143
144    yy = (1.0 - w_WR(q*sqrt(Rg2)))*Sdebye(q,L,b) + w_WR(q*sqrt(Rg2))*(C1*pow((q*sqrt(Rg2)),(-1.0/miu)) +  C2*pow((q*sqrt(Rg2)),(-2.0/miu)) +    C3*pow((q*sqrt(Rg2)),(-3.0/miu)));
145
146    return (yy);
147}
148
149// this must be WR modified version
150static double
151Sexvnew(double q, double L, double b)
152{
153    double yy,C1,C2,C3,miu;
154    double del=1.05,C_star2,Rg2;
155
156    C1=1.22;
157    C2=0.4288;
158    C3=-1.651;
159    miu = 0.585;
160
161    //calculating the derivative to decide on the corection (cutoff) term?
162    // I have modified this from WRs original code
163
164    if( (Sexv(q*del,L,b)-Sexv(q,L,b))/(q*del - q) >= 0.0 ) {
165        C_star2 = 0.0;
166    } else {
167        C_star2 = 1.0;
168    }
169
170    Rg2 = Rgsquare(q,L,b);
171
172  yy = (1.0 - w_WR(q*sqrt(Rg2)))*Sdebye(q,L,b) + C_star2*w_WR(q*sqrt(Rg2))*(C1*pow((q*sqrt(Rg2)),(-1.0/miu)) + C2*pow((q*sqrt(Rg2)),(-2.0/miu)) + C3*pow((q*sqrt(Rg2)),(-3.0/miu)));
173
174    return (yy);
175}
176
177// these are the messy ones
178static double
179a2short(double q, double L, double b, double p1short, double p2short, double q0)
180{
181    double yy,Rg2_sh;
182    double t1,E,Rg2_sh2,Et1,Emt1,q02,q0p;
183    double pi;
184
185    E = 2.718281828459045091;
186  pi = 4.0*atan(1.0);
187    Rg2_sh = Rgsquareshort(q,L,b);
188    Rg2_sh2 = Rg2_sh*Rg2_sh;
189    t1 = ((q0*q0*Rg2_sh)/(b*b));
190    Et1 = pow(E,t1);
191    Emt1 =pow(E,-t1);
192    q02 = q0*q0;
193    q0p = pow(q0,(-4.0 + p2short) );
194
195    //E is the number e
196    yy = ((-(1.0/(L*((p1short - p2short))*Rg2_sh2)*((b*Emt1*q0p*((8.0*b*b*b*L - 8.0*b*b*b*Et1*L - 2.0*b*b*b*L*p1short + 2.0*b*b*b*Et1*L*p1short + 4.0*b*L*q02*Rg2_sh + 4.0*b*Et1*L*q02*Rg2_sh - 2.0*b*Et1*L*p1short*q02*Rg2_sh - Et1*pi*q02*q0*Rg2_sh2 + Et1*p1short*pi*q02*q0*Rg2_sh2)))))));
197
198    return (yy);
199}
200
201//
202static double
203a1short(double q, double L, double b, double p1short, double p2short, double q0)
204{
205    double yy,Rg2_sh;
206    double t1,E,Rg2_sh2,Et1,Emt1,q02,q0p,b3;
207  double pi;
208
209    E = 2.718281828459045091;
210  pi = 4.0*atan(1.0);
211    Rg2_sh = Rgsquareshort(q,L,b);
212    Rg2_sh2 = Rg2_sh*Rg2_sh;
213    b3 = b*b*b;
214    t1 = ((q0*q0*Rg2_sh)/(b*b));
215    Et1 = pow(E,t1);
216    Emt1 =pow(E,-t1);
217    q02 = q0*q0;
218    q0p = pow(q0,(-4.0 + p1short) );
219
220    yy = ((1.0/(L*((p1short - p2short))*Rg2_sh2)*((b*Emt1*q0p*((8.0*b3*L - 8.0*b3*Et1*L - 2.0*b3*L*p2short + 2.0*b3*Et1*L*p2short + 4.0*b*L*q02*Rg2_sh + 4.0*b*Et1*L*q02*Rg2_sh - 2.0*b*Et1*L*p2short*q02*Rg2_sh - Et1*pi*q02*q0*Rg2_sh2 + Et1*p2short*pi*q02*q0*Rg2_sh2))))));
221
222    return(yy);
223}
224
225
226//need to define this on my own
227static double
228sech_WR(double x)
229{
230  return(1/cosh(x));
231}
232
233// this one will be lots of trouble
234static double
235a2long(double q, double L, double b, double p1, double p2, double q0)
236{
237    double yy,C1,C2,C3,C4,C5,miu,C,Rg2;
238    double t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,pi;
239    double E,b2,b3,b4,q02,q03,q04,q05,Rg22;
240
241    pi = 4.0*atan(1.0);
242    E = 2.718281828459045091;
243    if( L/b > 10.0) {
244        C = 3.06/pow((L/b),0.44);
245    } else {
246        C = 1.0;
247    }
248
249    C1 = 1.22;
250    C2 = 0.4288;
251    C3 = -1.651;
252    C4 = 1.523;
253    C5 = 0.1477;
254    miu = 0.585;
255
256    Rg2 = Rgsquare(q,L,b);
257    Rg22 = Rg2*Rg2;
258    b2 = b*b;
259    b3 = b*b*b;
260    b4 = b3*b;
261    q02 = q0*q0;
262    q03 = q0*q0*q0;
263    q04 = q03*q0;
264    q05 = q04*q0;
265
266    t1 = (1.0/(b* p1*pow(q0,((-1.0) - p1 - p2)) - b*p2*pow(q0,((-1.0) - p1 - p2)) ));
267
268    t2 = (b*C*(((-1.0*((14.0*b3)/(15.0*q03*Rg2))) + (14.0*b3*pow(E,(-((q02*Rg2)/b2))))/(15.0*q03*Rg2) + (2.0*pow(E,(-((q02*Rg2)/b2)))*q0*((11.0/15.0 + (7*b2)/(15.0*q02*Rg2)))*Rg2)/b)))/L;
269
270    t3 = (sqrt(Rg2)*((C3*pow((((sqrt(Rg2)*q0)/b)),((-3.0)/miu)) + C2*pow((((sqrt(Rg2)*q0)/b)),((-2.0)/miu)) + C1*pow((((sqrt(Rg2)*q0)/b)),((-1.0)/miu))))*pow(sech_WR(((-C4) + (sqrt(Rg2)*q0)/b)/C5),2.0))/(2.0*C5);
271
272    t4 = (b4*sqrt(Rg2)*(((-1.0) + pow(E,(-((q02*Rg2)/b2))) + (q02*Rg2)/b2))*pow(sech_WR(((-C4) + (sqrt(Rg2)*q0)/b)/C5),2))/(C5*q04*Rg22);
273
274    t5 = (2.0*b4*(((2.0*q0*Rg2)/b - (2.0*pow(E,(-((q02*Rg2)/b2)))*q0*Rg2)/b))*((1.0 + 1.0/2.0*(((-1.0) - tanh(((-C4) + (sqrt(Rg2)*q0)/b)/C5))))))/(q04*Rg22);
275
276    t6 = (8.0*b4*b*(((-1.0) + pow(E,(-((q02*Rg2)/b2))) + (q02*Rg2)/b2))*((1.0 + 1.0/2.0*(((-1) - tanh(((-C4) + (sqrt(Rg2)*q0)/b)/C5))))))/(q05*Rg22);
277
278    t7 = (((-((3.0*C3*sqrt(Rg2)*pow((((sqrt(Rg2)*q0)/b)),((-1.0) - 3.0/miu)))/miu)) - (2.0*C2*sqrt(Rg2)*pow((((sqrt(Rg2)*q0)/b)),((-1.0) - 2.0/miu)))/miu - (C1*sqrt(Rg2)*pow((((sqrt(Rg2)*q0)/b)),((-1.0) - 1.0/miu)))/miu));
279
280    t8 = ((1.0 + tanh(((-C4) + (sqrt(Rg2)*q0)/b)/C5)));
281
282    t9 = (b*C*((4.0/15.0 - pow(E,(-((q02*Rg2)/b2)))*((11.0/15.0 + (7.0*b2)/(15*q02*Rg2))) + (7.0*b2)/(15.0*q02*Rg2))))/L;
283
284    t10 = (2.0*b4*(((-1) + pow(E,(-((q02*Rg2)/b2))) + (q02*Rg2)/b2))*((1.0 + 1.0/2.0*(((-1) - tanh(((-C4) + (sqrt(Rg2)*q0)/b)/C5))))))/(q04*Rg22);
285
286
287    yy = ((-1.0*(t1* ((-pow(q0,-p1)*(((b2*pi)/(L*q02) + t2 + t3 - t4 + t5 - t6 + 1.0/2.0*t7*t8)) - b*p1*pow(q0,((-1.0) - p1))*(((-((b*pi)/(L*q0))) + t9 + t10 + 1.0/2.0*((C3*pow((((sqrt(Rg2)*q0)/b)),((-3.0)/miu)) + C2*pow((((sqrt(Rg2)*q0)/b)),((-2.0)/miu)) + C1*pow((((sqrt(Rg2)*q0)/b)),((-1.0)/miu))))*((1.0 + tanh(((-C4) + (sqrt(Rg2)*q0)/b)/C5))))))))));
288
289    return (yy);
290}
291//
292static double
293a1long(double q, double L, double b, double p1, double p2, double q0)
294{
295    double yy,C,C1,C2,C3,C4,C5,miu,Rg2;
296    double t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15;
297    double E,pi;
298    double b2,b3,b4,q02,q03,q04,q05,Rg22;
299
300    pi = 4.0*atan(1.0);
301    E = 2.718281828459045091;
302
303    if( L/b > 10.0) {
304        C = 3.06/pow((L/b),0.44);
305    } else {
306        C = 1.0;
307    }
308
309    C1 = 1.22;
310    C2 = 0.4288;
311    C3 = -1.651;
312    C4 = 1.523;
313    C5 = 0.1477;
314    miu = 0.585;
315
316    Rg2 = Rgsquare(q,L,b);
317    Rg22 = Rg2*Rg2;
318    b2 = b*b;
319    b3 = b*b*b;
320    b4 = b3*b;
321    q02 = q0*q0;
322    q03 = q0*q0*q0;
323    q04 = q03*q0;
324    q05 = q04*q0;
325
326    t1 = (b*C*((4.0/15.0 - pow(E,(-((q02*Rg2)/b2)))*((11.0/15.0 + (7.0*b2)/(15.0*q02*Rg2))) + (7.0*b2)/(15.0*q02*Rg2))));
327
328    t2 = (2.0*b4*(((-1.0) + pow(E,(-((q02*Rg2)/b2))) + (q02*Rg2)/b2))*((1.0 + 1.0/2.0*(((-1.0) - tanh(((-C4) + (sqrt(Rg2)*q0)/b)/C5))))));
329
330    t3 = ((C3*pow((((sqrt(Rg2)*q0)/b)),((-3.0)/miu)) + C2*pow((((sqrt(Rg2)*q0)/b)),((-2.0)/miu)) + C1*pow((((sqrt(Rg2)*q0)/b)),((-1.0)/miu))));
331
332    t4 = ((1.0 + tanh(((-C4) + (sqrt(Rg2)*q0)/b)/C5)));
333
334    t5 = (1.0/(b*p1*pow(q0,((-1.0) - p1 - p2)) - b*p2*pow(q0,((-1.0) - p1 - p2))));
335
336    t6 = (b*C*(((-((14.0*b3)/(15.0*q03*Rg2))) + (14.0*b3*pow(E,(-((q02*Rg2)/b2))))/(15.0*q03*Rg2) + (2.0*pow(E,(-((q02*Rg2)/b2)))*q0*((11.0/15.0 + (7.0*b2)/(15.0*q02*Rg2)))*Rg2)/b)));
337
338    t7 = (sqrt(Rg2)*((C3*pow((((sqrt(Rg2)*q0)/b)),((-3.0)/miu)) + C2*pow((((sqrt(Rg2)*q0)/b)),((-2.0)/miu)) + C1*pow((((sqrt(Rg2)*q0)/b)),((-1.0)/miu))))*pow(sech_WR(((-C4) + (sqrt(Rg2)*q0)/b)/C5),2));
339
340    t8 = (b4*sqrt(Rg2)*(((-1.0) + pow(E,(-((q02*Rg2)/b2))) + (q02*Rg2)/b2))*pow(sech_WR(((-C4) + (sqrt(Rg2)*q0)/b)/C5),2));
341
342    t9 = (2.0*b4*(((2.0*q0*Rg2)/b - (2.0*pow(E,(-((q02*Rg2)/b2)))*q0*Rg2)/b))*((1.0 + 1.0/2.0*(((-1.0) - tanh(((-C4) + (sqrt(Rg2)*q0)/b)/C5))))));
343
344    t10 = (8.0*b4*b*(((-1.0) + pow(E,(-((q02*Rg2)/b2))) + (q02*Rg2)/b2))*((1.0 + 1.0/2.0*(((-1.0) - tanh(((-C4) + (sqrt(Rg2)*q0)/b)/C5))))));
345
346    t11 = (((-((3.0*C3*sqrt(Rg2)*pow((((sqrt(Rg2)*q0)/b)),((-1.0) - 3.0/miu)))/miu)) - (2.0*C2*sqrt(Rg2)*pow((((sqrt(Rg2)*q0)/b)),((-1.0) - 2.0/miu)))/miu - (C1*sqrt(Rg2)*pow((((sqrt(Rg2)*q0)/b)),((-1.0) - 1.0/miu)))/miu));
347
348    t12 = ((1.0 + tanh(((-C4) + (sqrt(Rg2)*q0)/b)/C5)));
349
350    t13 = (b*C*((4.0/15.0 - pow(E,(-((q02*Rg2)/b2)))*((11.0/15.0 + (7.0*b2)/(15.0*q02* Rg2))) + (7.0*b2)/(15.0*q02*Rg2))));
351
352    t14 = (2.0*b4*(((-1.0) + pow(E,(-((q02*Rg2)/b2))) + (q02*Rg2)/b2))*((1.0 + 1.0/2.0*(((-1.0) - tanh(((-C4) + (sqrt(Rg2)*q0)/b)/C5))))));
353
354    t15 = ((C3*pow((((sqrt(Rg2)*q0)/b)),((-3.0)/miu)) + C2*pow((((sqrt(Rg2)*q0)/b)),((-2.0)/miu)) + C1*pow((((sqrt(Rg2)*q0)/b)),((-1.0)/miu))));
355
356
357    yy = (pow(q0,p1)*(((-((b*pi)/(L*q0))) +t1/L +t2/(q04*Rg22) + 1.0/2.0*t3*t4)) + (t5*((pow(q0,(p1 - p2))*(((-pow(q0,(-p1)))*(((b2*pi)/(L*q02) +t6/L +t7/(2.0*C5) -t8/(C5*q04*Rg22) +t9/(q04*Rg22) -t10/(q05*Rg22) + 1.0/2.0*t11*t12)) - b*p1*pow(q0,((-1.0) - p1))*(((-((b*pi)/(L*q0))) +t13/L +t14/(q04*Rg22) + 1.0/2.0*t15*((1.0 + tanh(((-C4) + (sqrt(Rg2)*q0)/b)/C5)))))))))));
358
359    return (yy);
360}
361
362
363static double
364Sk_WR(double q, double L, double b)
365{
366  //
367  double p1,p2,p1short,p2short,q0;
368  double C,ans,q0short,Sexvmodify,pi;
369
370  pi = 4.0*atan(1.0);
371
372  p1 = 4.12;
373  p2 = 4.42;
374  p1short = 5.36;
375  p2short = 5.62;
376  q0 = 3.1;
377  //
378  q0short = fmax(1.9/sqrt(Rgsquareshort(q,L,b)),3.0);
379
380  //
381  if(L/b > 10.0) {
382    C = 3.06/pow((L/b),0.44);
383  } else {
384    C = 1.0;
385  }
386  //
387
388  if( L > 4*b ) { // Longer Chains
389    if (q*b <= 3.1) {   //Modified by Yun on Oct. 15,
390      Sexvmodify = Sexvnew(q, L, b);
391      ans = Sexvmodify + C * (4.0/15.0 + 7.0/(15.0*u_WR(q,L,b)) - (11.0/15.0 + 7.0/(15.0*u_WR(q,L,b)))*exp(-u_WR(q,L,b)))*(b/L);
392    } else { //q(i)*b > 3.1
393      ans = a1long(q, L, b, p1, p2, q0)/(pow((q*b),p1)) + a2long(q, L, b, p1, p2, q0)/(pow((q*b),p2)) + pi/(q*L);
394    }
395  } else { //L <= 4*b Shorter Chains
396    if (q*b <= fmax(1.9/sqrt(Rgsquareshort(q,L,b)),3.0) ) {
397      if (q*b<=0.01) {
398        ans = 1.0 - Rgsquareshort(q,L,b)*(q*q)/3.0;
399      } else {
400        ans = Sdebye1(q,L,b);
401      }
402    } else {  //q*b > max(1.9/sqrt(Rgsquareshort(q(i),L,b)),3)
403      ans = a1short(q,L,b,p1short,p2short,q0short)/(pow((q*b),p1short)) + a2short(q,L,b,p1short,p2short,q0short)/(pow((q*b),p2short)) + pi/(q*L);
404    }
405  }
406
407  return(ans);
408  //return(a2long(q, L, b, p1, p2, q0));
409}
410
411/*      CylinderForm  :  calculates the form factor of a cylinder at the give x-value p->x
412
413Warning:
414The call to WaveData() below returns a pointer to the middle
415of an unlocked Macintosh handle. In the unlikely event that your
416calculations could cause memory to move, you should copy the coefficient
417values to local variables or an array before such operations.
418*/
419double
420CylinderForm(double dp[], double q)
421{
422
423        int i;
424        double Pi;
425        double scale,radius,length,delrho,bkg,halfheight,sldCyl,sldSolv;                //local variables of coefficient wave
426        int nord=76;                    //order of integration
427        double uplim,lolim;             //upper and lower integration limits
428        double summ,zi,yyy,answer,vcyl;                 //running tally of integration
429       
430        Pi = 4.0*atan(1.0);
431        lolim = 0.0;
432        uplim = Pi/2.0;
433       
434        summ = 0.0;                     //initialize intergral
435       
436        scale = dp[0];                  //make local copies in case memory moves
437        radius = dp[1];
438        length = dp[2];
439        sldCyl = dp[3];
440        sldSolv = dp[4];
441        bkg = dp[5];
442       
443        delrho = sldCyl-sldSolv;
444        halfheight = length/2.0;
445        for(i=0;i<nord;i++) {
446                zi = ( Gauss76Z[i]*(uplim-lolim) + uplim + lolim )/2.0;
447                yyy = Gauss76Wt[i] * CylKernel(q, radius, halfheight, zi);
448                summ += yyy;
449        }
450       
451        answer = (uplim-lolim)/2.0*summ;
452        // Multiply by contrast^2
453        answer *= delrho*delrho;
454        //normalize by cylinder volume
455        //NOTE that for this (Fournet) definition of the integral, one must MULTIPLY by Vcyl
456        vcyl=Pi*radius*radius*length;
457        answer *= vcyl;
458        //convert to [cm-1]
459        answer *= 1.0e8;
460        //Scale
461        answer *= scale;
462        // add in the background
463        answer += bkg;
464       
465        return answer;
466}
467
468/*      EllipCyl76X  :  calculates the form factor of a elliptical cylinder at the given x-value p->x
469
470Uses 76 pt Gaussian quadrature for both integrals
471
472Warning:
473The call to WaveData() below returns a pointer to the middle
474of an unlocked Macintosh handle. In the unlikely event that your
475calculations could cause memory to move, you should copy the coefficient
476values to local variables or an array before such operations.
477*/
478double
479EllipCyl76(double dp[], double q)
480{
481        int i,j;
482        double Pi,slde,sld;
483        double scale,ra,nu,length,delrho,bkg;           //local variables of coefficient wave
484        int nord=76;                    //order of integration
485        double va,vb;           //upper and lower integration limits
486        double summ,zi,yyy,answer,vell;                 //running tally of integration
487        double summj,vaj,vbj,zij,arg, si;                       //for the inner integration
488
489        Pi = 4.0*atan(1.0);
490        va = 0.0;
491        vb = 1.0;               //orintational average, outer integral
492        vaj=0.0;
493        vbj=Pi;         //endpoints of inner integral
494       
495        summ = 0.0;                     //initialize intergral
496       
497        scale = dp[0];                  //make local copies in case memory moves
498        ra = dp[1];
499        nu = dp[2];
500        length = dp[3];
501        slde = dp[4];
502        sld = dp[5];
503        delrho = slde - sld;
504        bkg = dp[6];
505       
506        for(i=0;i<nord;i++) {
507                //setup inner integral over the ellipsoidal cross-section
508                summj=0;
509                zi = ( Gauss76Z[i]*(vb-va) + va + vb )/2.0;             //the "x" dummy
510                arg = ra*sqrt(1.0-zi*zi);
511                for(j=0;j<nord;j++) {
512                        //76 gauss points for the inner integral as well
513                        zij = ( Gauss76Z[j]*(vbj-vaj) + vaj + vbj )/2.0;                //the "y" dummy
514                        yyy = Gauss76Wt[j] * EllipCylKernel(q,arg,nu,zij);
515                        summj += yyy;
516                }
517                //now calculate the value of the inner integral
518                answer = (vbj-vaj)/2.0*summj;
519                //divide integral by Pi
520                answer /=Pi;
521               
522                //now calculate outer integral
523                arg = q*length*zi/2.0;
524                if (arg == 0.0){
525                        si = 1.0;
526                }else{
527                        si = sin(arg) * sin(arg) / arg / arg;
528                }
529                yyy = Gauss76Wt[i] * answer * si;
530                summ += yyy;
531        }
532        answer = (vb-va)/2.0*summ;
533        // Multiply by contrast^2
534        answer *= delrho*delrho;
535        //normalize by cylinder volume
536        //NOTE that for this (Fournet) definition of the integral, one must MULTIPLY by Vcyl
537        vell = Pi*ra*(nu*ra)*length;
538        answer *= vell;
539        //convert to [cm-1]
540        answer *= 1.0e8;
541        //Scale
542        answer *= scale;
543        // add in the background
544        answer += bkg;
545       
546        return answer;
547}
548
549/*      EllipCyl20X  :  calculates the form factor of a elliptical cylinder at the given x-value p->x
550
551Uses 76 pt Gaussian quadrature for orientational integral
552Uses 20 pt quadrature for the inner integral over the elliptical cross-section
553
554Warning:
555The call to WaveData() below returns a pointer to the middle
556of an unlocked Macintosh handle. In the unlikely event that your
557calculations could cause memory to move, you should copy the coefficient
558values to local variables or an array before such operations.
559*/
560double
561EllipCyl20(double dp[], double q)
562{
563        int i,j;
564        double Pi,slde,sld;
565        double scale,ra,nu,length,delrho,bkg;           //local variables of coefficient wave
566        int nordi=76;                   //order of integration
567        int nordj=20;
568        double va,vb;           //upper and lower integration limits
569        double summ,zi,yyy,answer,vell;                 //running tally of integration
570        double summj,vaj,vbj,zij,arg,si;                        //for the inner integration
571
572        Pi = 4.0*atan(1.0);
573        va = 0.0;
574        vb = 1.0;               //orintational average, outer integral
575        vaj=0.0;
576        vbj=Pi;         //endpoints of inner integral
577       
578        summ = 0.0;                     //initialize intergral
579       
580        scale = dp[0];                  //make local copies in case memory moves
581        ra = dp[1];
582        nu = dp[2];
583        length = dp[3];
584        slde = dp[4];
585        sld = dp[5];
586        delrho = slde - sld;
587        bkg = dp[6];
588       
589        for(i=0;i<nordi;i++) {
590                //setup inner integral over the ellipsoidal cross-section
591                summj=0;
592                zi = ( Gauss76Z[i]*(vb-va) + va + vb )/2.0;             //the "x" dummy
593                arg = ra*sqrt(1.0-zi*zi);
594                for(j=0;j<nordj;j++) {
595                        //20 gauss points for the inner integral
596                        zij = ( Gauss20Z[j]*(vbj-vaj) + vaj + vbj )/2.0;                //the "y" dummy
597                        yyy = Gauss20Wt[j] * EllipCylKernel(q,arg,nu,zij);
598                        summj += yyy;
599                }
600                //now calculate the value of the inner integral
601                answer = (vbj-vaj)/2.0*summj;
602                //divide integral by Pi
603                answer /=Pi;
604               
605                //now calculate outer integral
606                arg = q*length*zi/2.0;
607                if (arg == 0.0){
608                        si = 1.0;
609                }else{
610                        si = sin(arg) * sin(arg) / arg / arg;
611                }
612                yyy = Gauss76Wt[i] * answer * si;
613                summ += yyy;
614        }
615       
616        answer = (vb-va)/2.0*summ;
617        // Multiply by contrast^2
618        answer *= delrho*delrho;
619        //normalize by cylinder volume
620        //NOTE that for this (Fournet) definition of the integral, one must MULTIPLY by Vcyl
621        vell = Pi*ra*(nu*ra)*length;
622        answer *= vell;
623        //convert to [cm-1]
624        answer *= 1.0e8;
625        //Scale
626        answer *= scale;
627        // add in the background
628        answer += bkg;
629
630        return answer;
631}
632
633/*      TriaxialEllipsoidX  :  calculates the form factor of a Triaxial Ellipsoid at the given x-value p->x
634
635Uses 76 pt Gaussian quadrature for both integrals
636
637Warning:
638The call to WaveData() below returns a pointer to the middle
639of an unlocked Macintosh handle. In the unlikely event that your
640calculations could cause memory to move, you should copy the coefficient
641values to local variables or an array before such operations.
642*/
643double
644TriaxialEllipsoid(double dp[], double q)
645{
646        int i,j;
647        double Pi;
648        double scale,aa,bb,cc,delrho,bkg;               //local variables of coefficient wave
649        int nordi=76;                   //order of integration
650        int nordj=76;
651        double va,vb;           //upper and lower integration limits
652        double summ,zi,yyy,answer;                      //running tally of integration
653        double summj,vaj,vbj,zij,slde,sld;                      //for the inner integration
654       
655        Pi = 4.0*atan(1.0);
656        va = 0.0;
657        vb = 1.0;               //orintational average, outer integral
658        vaj = 0.0;
659        vbj = 1.0;              //endpoints of inner integral
660       
661        summ = 0.0;                     //initialize intergral
662       
663        scale = dp[0];                  //make local copies in case memory moves
664        aa = dp[1];
665        bb = dp[2];
666        cc = dp[3];
667        slde = dp[4];
668        sld = dp[5];
669        delrho = slde - sld;
670        bkg = dp[6];
671        for(i=0;i<nordi;i++) {
672                //setup inner integral over the ellipsoidal cross-section
673                summj=0.0;
674                zi = ( Gauss76Z[i]*(vb-va) + va + vb )/2.0;             //the "x" dummy
675                for(j=0;j<nordj;j++) {
676                        //20 gauss points for the inner integral
677                        zij = ( Gauss76Z[j]*(vbj-vaj) + vaj + vbj )/2.0;                //the "y" dummy
678                        yyy = Gauss76Wt[j] * TriaxialKernel(q,aa,bb,cc,zi,zij);
679                        summj += yyy;
680                }
681                //now calculate the value of the inner integral
682                answer = (vbj-vaj)/2.0*summj;
683               
684                //now calculate outer integral
685                yyy = Gauss76Wt[i] * answer;
686                summ += yyy;
687        }               //final scaling is done at the end of the function, after the NT_FP64 case
688       
689        answer = (vb-va)/2.0*summ;
690        // Multiply by contrast^2
691        answer *= delrho*delrho;
692        //normalize by ellipsoid volume
693        answer *= 4.0*Pi/3.0*aa*bb*cc;
694        //convert to [cm-1]
695        answer *= 1.0e8;
696        //Scale
697        answer *= scale;
698        // add in the background
699        answer += bkg;
700       
701        return answer;
702}
703
704/*      ParallelepipedX  :  calculates the form factor of a Parallelepiped (a rectangular solid)
705at the given x-value p->x
706
707Uses 76 pt Gaussian quadrature for both integrals
708
709Warning:
710The call to WaveData() below returns a pointer to the middle
711of an unlocked Macintosh handle. In the unlikely event that your
712calculations could cause memory to move, you should copy the coefficient
713values to local variables or an array before such operations.
714*/
715double
716Parallelepiped(double dp[], double q)
717{
718        int i,j;
719        double scale,aa,bb,cc,delrho,bkg;               //local variables of coefficient wave
720        int nordi=76;                   //order of integration
721        int nordj=76;
722        double va,vb;           //upper and lower integration limits
723        double summ,yyy,answer;                 //running tally of integration
724        double summj,vaj,vbj;                   //for the inner integration
725        double mu,mudum,arg,sigma,uu,vol,sldp,sld;
726       
727       
728        //      Pi = 4.0*atan(1.0);
729        va = 0.0;
730        vb = 1.0;               //orintational average, outer integral
731        vaj = 0.0;
732        vbj = 1.0;              //endpoints of inner integral
733
734        summ = 0.0;                     //initialize intergral
735       
736        scale = dp[0];                  //make local copies in case memory moves
737        aa = dp[1];
738        bb = dp[2];
739        cc = dp[3];
740        sldp = dp[4];
741        sld = dp[5];
742        delrho = sldp - sld;
743        bkg = dp[6];
744       
745        mu = q*bb;
746        vol = aa*bb*cc;
747        // normalize all WRT bb
748        aa = aa/bb;
749        cc = cc/bb;
750       
751        for(i=0;i<nordi;i++) {
752                //setup inner integral over the ellipsoidal cross-section
753                summj=0.0;
754                sigma = ( Gauss76Z[i]*(vb-va) + va + vb )/2.0;          //the outer dummy
755               
756                for(j=0;j<nordj;j++) {
757                        //76 gauss points for the inner integral
758                        uu = ( Gauss76Z[j]*(vbj-vaj) + vaj + vbj )/2.0;         //the inner dummy
759                        mudum = mu*sqrt(1.0-sigma*sigma);
760                        yyy = Gauss76Wt[j] * PPKernel(aa,mudum,uu);
761                        summj += yyy;
762                }
763                //now calculate the value of the inner integral
764                answer = (vbj-vaj)/2.0*summj;
765
766                arg = mu*cc*sigma/2.0;
767                if ( arg == 0.0 ) {
768                        answer *= 1.0;
769                } else {
770                        answer *= sin(arg)*sin(arg)/arg/arg;
771                }
772               
773                //now sum up the outer integral
774                yyy = Gauss76Wt[i] * answer;
775                summ += yyy;
776        }               //final scaling is done at the end of the function, after the NT_FP64 case
777       
778        answer = (vb-va)/2.0*summ;
779        // Multiply by contrast^2
780        answer *= delrho*delrho;
781        //normalize by volume
782        answer *= vol;
783        //convert to [cm-1]
784        answer *= 1.0e8;
785        //Scale
786        answer *= scale;
787        // add in the background
788        answer += bkg;
789       
790        return answer;
791}
792
793/*      HollowCylinderX  :  calculates the form factor of a Hollow Cylinder
794at the given x-value p->x
795
796Uses 76 pt Gaussian quadrature for the single integral
797
798Warning:
799The call to WaveData() below returns a pointer to the middle
800of an unlocked Macintosh handle. In the unlikely event that your
801calculations could cause memory to move, you should copy the coefficient
802values to local variables or an array before such operations.
803*/
804double
805HollowCylinder(double dp[], double q)
806{
807        int i;
808        double scale,rcore,rshell,length,delrho,bkg;            //local variables of coefficient wave
809        int nord=76;                    //order of integration
810        double va,vb,zi;                //upper and lower integration limits
811        double summ,answer,pi,sldc,sld;                 //running tally of integration
812       
813        pi = 4.0*atan(1.0);
814        va = 0.0;
815        vb = 1.0;               //limits of numerical integral
816
817        summ = 0.0;                     //initialize intergral
818       
819        scale = dp[0];          //make local copies in case memory moves
820        rcore = dp[1];
821        rshell = dp[2];
822        length = dp[3];
823        sldc = dp[4];
824        sld = dp[5];
825        delrho = sldc - sld;
826        bkg = dp[6];
827       
828        for(i=0;i<nord;i++) {
829                zi = ( Gauss76Z[i]*(vb-va) + va + vb )/2.0;
830                summ += Gauss76Wt[i] * HolCylKernel(q, rcore, rshell, length, zi);
831        }
832       
833        answer = (vb-va)/2.0*summ;
834        // Multiply by contrast^2
835        answer *= delrho*delrho;
836        //normalize by volume
837        answer *= pi*(rshell*rshell-rcore*rcore)*length;
838        //convert to [cm-1]
839        answer *= 1.0e8;
840        //Scale
841        answer *= scale;
842        // add in the background
843        answer += bkg;
844       
845        return answer;
846}
847
848/*      EllipsoidFormX  :  calculates the form factor of an ellipsoid of revolution with semiaxes a:a:nua
849at the given x-value p->x
850
851Uses 76 pt Gaussian quadrature for the single integral
852
853Warning:
854The call to WaveData() below returns a pointer to the middle
855of an unlocked Macintosh handle. In the unlikely event that your
856calculations could cause memory to move, you should copy the coefficient
857values to local variables or an array before such operations.
858*/
859double
860EllipsoidForm(double dp[], double q)
861{
862        int i;
863        double scale,a,nua,delrho,bkg;          //local variables of coefficient wave
864        int nord=76;                    //order of integration
865        double va,vb,zi;                //upper and lower integration limits
866        double summ,answer,pi,slde,sld;                 //running tally of integration
867       
868        pi = 4.0*atan(1.0);
869        va = 0.0;
870        vb = 1.0;               //limits of numerical integral
871
872        summ = 0.0;                     //initialize intergral
873       
874        scale = dp[0];                  //make local copies in case memory moves
875        nua = dp[1];
876        a = dp[2];
877        slde = dp[3];
878        sld = dp[4];
879        delrho = slde - sld;
880        bkg = dp[5];
881       
882        for(i=0;i<nord;i++) {
883                zi = ( Gauss76Z[i]*(vb-va) + va + vb )/2.0;
884                summ += Gauss76Wt[i] * EllipsoidKernel(q, a, nua, zi);
885        }
886       
887        answer = (vb-va)/2.0*summ;
888        // Multiply by contrast^2
889        answer *= delrho*delrho;
890        //normalize by volume
891        answer *= 4.0*pi/3.0*a*a*nua;
892        //convert to [cm-1]
893        answer *= 1.0e8;
894        //Scale
895        answer *= scale;
896        // add in the background
897        answer += bkg;
898       
899        return answer;
900}
901
902
903/*      Cyl_PolyRadiusX  :  calculates the form factor of a cylinder at the given x-value p->x
904the cylinder has a polydisperse cross section
905
906*/
907double
908Cyl_PolyRadius(double dp[], double q)
909{
910        int i;
911        double scale,radius,length,pd,delrho,bkg;               //local variables of coefficient wave
912        int nord=20;                    //order of integration
913        double uplim,lolim;             //upper and lower integration limits
914        double summ,zi,yyy,answer,Vpoly;                        //running tally of integration
915        double range,zz,Pi,sldc,sld;
916       
917        Pi = 4.0*atan(1.0);
918        range = 3.4;
919       
920        summ = 0.0;                     //initialize intergral
921       
922        scale = dp[0];                  //make local copies in case memory moves
923        radius = dp[1];
924        length = dp[2];
925        pd = dp[3];
926        sldc = dp[4];
927        sld = dp[5];
928        delrho = sldc - sld;
929        bkg = dp[6];
930       
931        zz = (1.0/pd)*(1.0/pd) - 1.0;
932       
933        lolim = radius*(1.0-range*pd);          //set the upper/lower limits to cover the distribution
934        if(lolim<0.0) {
935                lolim = 0.0;
936        }
937        if(pd>0.3) {
938                range = 3.4 + (pd-0.3)*18.0;
939        }
940        uplim = radius*(1.0+range*pd);
941       
942        for(i=0;i<nord;i++) {
943                zi = ( Gauss20Z[i]*(uplim-lolim) + uplim + lolim )/2.0;
944                yyy = Gauss20Wt[i] * Cyl_PolyRadKernel(q, radius, length, zz, delrho, zi);
945                summ += yyy;
946        }
947       
948        answer = (uplim-lolim)/2.0*summ;
949        //normalize by average cylinder volume
950        //NOTE that for this (Fournet) definition of the integral, one must MULTIPLY by Vcyl
951        Vpoly=Pi*radius*radius*length*(zz+2.0)/(zz+1.0);
952        answer /= Vpoly;
953        //convert to [cm-1]
954        answer *= 1.0e8;
955        //Scale
956        answer *= scale;
957        // add in the background
958        answer += bkg;
959       
960        return answer;
961}
962
963/*      Cyl_PolyLengthX  :  calculates the form factor of a cylinder at the given x-value p->x
964the cylinder has a polydisperse Length
965
966*/
967double
968Cyl_PolyLength(double dp[], double q)
969{
970        int i;
971        double scale,radius,length,pd,delrho,bkg;               //local variables of coefficient wave
972        int nord=20;                    //order of integration
973        double uplim,lolim;             //upper and lower integration limits
974        double summ,zi,yyy,answer,Vpoly;                        //running tally of integration
975        double range,zz,Pi,sldc,sld;
976       
977       
978        Pi = 4.0*atan(1.0);
979        range = 3.4;
980       
981        summ = 0.0;                     //initialize intergral
982       
983        scale = dp[0];                  //make local copies in case memory moves
984        radius = dp[1];
985        length = dp[2];
986        pd = dp[3];
987        sldc = dp[4];
988        sld = dp[5];
989        delrho = sldc - sld;
990        bkg = dp[6];
991       
992        zz = (1.0/pd)*(1.0/pd) - 1.0;
993       
994        lolim = length*(1.0-range*pd);          //set the upper/lower limits to cover the distribution
995        if(lolim<0.0) {
996                lolim = 0.0;
997        }
998        if(pd>0.3) {
999                range = 3.4 + (pd-0.3)*18.0;
1000        }
1001        uplim = length*(1.0+range*pd);
1002       
1003        for(i=0;i<nord;i++) {
1004                zi = ( Gauss20Z[i]*(uplim-lolim) + uplim + lolim )/2.0;
1005                yyy = Gauss20Wt[i] * Cyl_PolyLenKernel(q, radius, length, zz, delrho, zi);
1006                summ += yyy;
1007        }
1008       
1009        answer = (uplim-lolim)/2.0*summ;
1010        //normalize by average cylinder volume (first moment)
1011        //NOTE that for this (Fournet) definition of the integral, one must MULTIPLY by Vcyl
1012        Vpoly=Pi*radius*radius*length;
1013        answer /= Vpoly;
1014        //convert to [cm-1]
1015        answer *= 1.0e8;
1016        //Scale
1017        answer *= scale;
1018        // add in the background
1019        answer += bkg;
1020       
1021        return answer;
1022}
1023
1024/*      CoreShellCylinderX  :  calculates the form factor of a cylinder at the given x-value p->x
1025the cylinder has a core-shell structure
1026
1027*/
1028double
1029CoreShellCylinder(double dp[], double q)
1030{
1031        int i;
1032        double scale,rcore,length,bkg;          //local variables of coefficient wave
1033        double thick,rhoc,rhos,rhosolv;
1034        int nord=76;                    //order of integration
1035        double uplim,lolim,halfheight;          //upper and lower integration limits
1036        double summ,zi,yyy,answer,Vcyl;                 //running tally of integration
1037        double Pi;
1038       
1039        Pi = 4.0*atan(1.0);
1040       
1041        lolim = 0.0;
1042        uplim = Pi/2.0;
1043       
1044        summ = 0.0;                     //initialize intergral
1045       
1046        scale = dp[0];          //make local copies in case memory moves
1047        rcore = dp[1];
1048        thick = dp[2];
1049        length = dp[3];
1050        rhoc = dp[4];
1051        rhos = dp[5];
1052        rhosolv = dp[6];
1053        bkg = dp[7];
1054       
1055        halfheight = length/2.0;
1056       
1057        for(i=0;i<nord;i++) {
1058                zi = ( Gauss76Z[i]*(uplim-lolim) + uplim + lolim )/2.0;
1059                yyy = Gauss76Wt[i] * CoreShellCylKernel(q, rcore, thick, rhoc,rhos,rhosolv, halfheight, zi);
1060                summ += yyy;
1061        }
1062       
1063        answer = (uplim-lolim)/2.0*summ;
1064        // length is the total core length
1065        Vcyl=Pi*(rcore+thick)*(rcore+thick)*(length+2.0*thick);
1066        answer /= Vcyl;
1067        //convert to [cm-1]
1068        answer *= 1.0e8;
1069        //Scale
1070        answer *= scale;
1071        // add in the background
1072        answer += bkg;
1073       
1074        return answer;
1075}
1076
1077
1078/*      PolyCoShCylinderX  :  calculates the form factor of a core-shell cylinder at the given x-value p->x
1079the cylinder has a polydisperse CORE radius
1080
1081*/
1082double
1083PolyCoShCylinder(double dp[], double q)
1084{
1085        int i;
1086        double scale,radius,length,sigma,bkg;           //local variables of coefficient wave
1087        double rad,radthick,facthick,rhoc,rhos,rhosolv;
1088        int nord=20;                    //order of integration
1089        double uplim,lolim;             //upper and lower integration limits
1090        double summ,yyy,answer,Vpoly;                   //running tally of integration
1091        double Pi,AR,Rsqrsumm,Rsqryyy,Rsqr;
1092               
1093        Pi = 4.0*atan(1.0);
1094       
1095        summ = 0.0;                     //initialize intergral
1096        Rsqrsumm = 0.0;
1097       
1098        scale = dp[0];
1099        radius = dp[1];
1100        sigma = dp[2];                          //sigma is the standard mean deviation
1101        length = dp[3];
1102        radthick = dp[4];
1103        facthick= dp[5];
1104        rhoc = dp[6];
1105        rhos = dp[7];
1106        rhosolv = dp[8];
1107        bkg = dp[9];
1108       
1109        lolim = exp(log(radius)-(4.*sigma));
1110        if (lolim<0.0) {
1111                lolim=0.0;              //to avoid numerical error when  va<0 (-ve r value)
1112        }
1113        uplim = exp(log(radius)+(4.*sigma));
1114       
1115        for(i=0;i<nord;i++) {
1116                rad = ( Gauss20Z[i]*(uplim-lolim) + uplim + lolim )/2.0;
1117                AR=(1.0/(rad*sigma*sqrt(2.0*Pi)))*exp(-(0.5*((log(radius/rad))/sigma)*((log(radius/rad))/sigma)));
1118                yyy = AR* Gauss20Wt[i] * CSCylIntegration(q,rad,radthick,facthick,rhoc,rhos,rhosolv,length);
1119                Rsqryyy= Gauss20Wt[i] * AR * (rad+radthick)*(rad+radthick);             //SRK normalize to total dimensions
1120                summ += yyy;
1121                Rsqrsumm += Rsqryyy;
1122        }
1123       
1124        answer = (uplim-lolim)/2.0*summ;
1125        Rsqr = (uplim-lolim)/2.0*Rsqrsumm;
1126        //normalize by average cylinder volume
1127        Vpoly = Pi*Rsqr*(length+2*facthick);
1128        answer /= Vpoly;
1129        //convert to [cm-1]
1130        answer *= 1.0e8;
1131        //Scale
1132        answer *= scale;
1133        // add in the background
1134        answer += bkg;
1135       
1136        return answer;
1137}
1138
1139/*      OblateFormX  :  calculates the form factor of a core-shell Oblate ellipsoid at the given x-value p->x
1140the ellipsoid has a core-shell structure
1141
1142*/
1143double
1144OblateForm(double dp[], double q)
1145{
1146        int i;
1147        double scale,crmaj,crmin,trmaj,trmin,delpc,delps,bkg;
1148        int nord=76;                    //order of integration
1149        double uplim,lolim;             //upper and lower integration limits
1150        double summ,zi,yyy,answer,oblatevol;                    //running tally of integration
1151        double Pi,sldc,slds,sld;
1152       
1153        Pi = 4.0*atan(1.0);
1154       
1155        lolim = 0.0;
1156        uplim = 1.0;
1157       
1158        summ = 0.0;                     //initialize intergral
1159       
1160       
1161        scale = dp[0];          //make local copies in case memory moves
1162        crmaj = dp[1];
1163        crmin = dp[2];
1164        trmaj = dp[3];
1165        trmin = dp[4];
1166        sldc = dp[5];
1167        slds = dp[6];
1168        sld = dp[7];
1169        delpc = sldc - slds;    //core - shell
1170        delps = slds - sld;             //shell - solvent
1171        bkg = dp[8];
1172
1173        for(i=0;i<nord;i++) {
1174                zi = ( Gauss76Z[i]*(uplim-lolim) + uplim + lolim )/2.0;
1175                yyy = Gauss76Wt[i] * gfn4(zi,crmaj,crmin,trmaj,trmin,delpc,delps,q);
1176                summ += yyy;
1177        }
1178       
1179        answer = (uplim-lolim)/2.0*summ;
1180        // normalize by particle volume
1181        oblatevol = 4.0*Pi/3.0*trmaj*trmaj*trmin;
1182        answer /= oblatevol;
1183       
1184        //convert to [cm-1]
1185        answer *= 1.0e8;
1186        //Scale
1187        answer *= scale;
1188        // add in the background
1189        answer += bkg;
1190       
1191        return answer;
1192}
1193
1194/*      ProlateFormX  :  calculates the form factor of a core-shell Prolate ellipsoid at the given x-value p->x
1195the ellipsoid has a core-shell structure
1196
1197*/
1198double
1199ProlateForm(double dp[], double q)
1200{
1201        int i;
1202        double scale,crmaj,crmin,trmaj,trmin,delpc,delps,bkg;
1203        int nord=76;                    //order of integration
1204        double uplim,lolim;             //upper and lower integration limits
1205        double summ,zi,yyy,answer,prolatevol;                   //running tally of integration
1206        double Pi,sldc,slds,sld;
1207       
1208        Pi = 4.0*atan(1.0);
1209       
1210        lolim = 0.0;
1211        uplim = 1.0;
1212       
1213        summ = 0.0;                     //initialize intergral
1214       
1215        scale = dp[0];          //make local copies in case memory moves
1216        crmaj = dp[1];
1217        crmin = dp[2];
1218        trmaj = dp[3];
1219        trmin = dp[4];
1220        sldc = dp[5];
1221        slds = dp[6];
1222        sld = dp[7];
1223        delpc = sldc - slds;            //core - shell
1224        delps = slds - sld;             //shell  - sovent
1225        bkg = dp[8];
1226
1227        for(i=0;i<nord;i++) {
1228                zi = ( Gauss76Z[i]*(uplim-lolim) + uplim + lolim )/2.0;
1229                yyy = Gauss76Wt[i] * gfn2(zi,crmaj,crmin,trmaj,trmin,delpc,delps,q);
1230                summ += yyy;
1231        }
1232       
1233        answer = (uplim-lolim)/2.0*summ;
1234        // normalize by particle volume
1235        prolatevol = 4.0*Pi/3.0*trmaj*trmin*trmin;
1236        answer /= prolatevol;
1237       
1238        //convert to [cm-1]
1239        answer *= 1.0e8;
1240        //Scale
1241        answer *= scale;
1242        // add in the background
1243        answer += bkg;
1244       
1245        return answer;
1246}
1247
1248
1249/*      StackedDiscsX  :  calculates the form factor of a stacked "tactoid" of core shell disks
1250like clay platelets that are not exfoliated
1251
1252*/
1253double
1254StackedDiscs(double dp[], double q)
1255{
1256        int i;
1257        double scale,length,bkg,rcore,thick,rhoc,rhol,rhosolv,N,gsd;            //local variables of coefficient wave
1258        double va,vb,vcyl,summ,yyy,zi,halfheight,d,answer;
1259        int nord=76;                    //order of integration
1260        double Pi;
1261       
1262       
1263        Pi = 4.0*atan(1.0);
1264       
1265        va = 0.0;
1266        vb = Pi/2.0;
1267       
1268        summ = 0.0;                     //initialize intergral
1269       
1270        scale = dp[0];
1271        rcore = dp[1];
1272        length = dp[2];
1273        thick = dp[3];
1274        rhoc = dp[4];
1275        rhol = dp[5];
1276        rhosolv = dp[6];
1277        N = dp[7];
1278        gsd = dp[8];
1279        bkg = dp[9];
1280       
1281        d=2.0*thick+length;
1282        halfheight = length/2.0;
1283       
1284        for(i=0;i<nord;i++) {
1285                zi = ( Gauss76Z[i]*(vb-va) + vb + va )/2.0;
1286                yyy = Gauss76Wt[i] * Stackdisc_kern(q, rcore, rhoc,rhol,rhosolv, halfheight,thick,zi,gsd,d,N);
1287                summ += yyy;
1288        }
1289       
1290        answer = (vb-va)/2.0*summ;
1291        // length is the total core length
1292        vcyl=Pi*rcore*rcore*(2.0*thick+length)*N;
1293        answer /= vcyl;
1294        //Convert to [cm-1]
1295        answer *= 1.0e8;
1296        //Scale
1297        answer *= scale;
1298        // add in the background
1299        answer += bkg;
1300       
1301        return answer;
1302}
1303
1304
1305/*      LamellarFFX  :  calculates the form factor of a lamellar structure - no S(q) effects included
1306
1307*/
1308double
1309LamellarFF(double dp[], double q)
1310{
1311        double scale,del,sig,contr,bkg;         //local variables of coefficient wave
1312        double inten, qval,Pq;
1313        double Pi,sldb,sld;
1314       
1315       
1316        Pi = 4.0*atan(1.0);
1317        scale = dp[0];
1318        del = dp[1];
1319        sig = dp[2]*del;
1320        sldb = dp[3];
1321        sld = dp[4];
1322        contr = sldb - sld;
1323        bkg = dp[5];
1324        qval=q;
1325       
1326        Pq = 2.0*contr*contr/qval/qval*(1.0-cos(qval*del)*exp(-0.5*qval*qval*sig*sig));
1327       
1328        inten = 2.0*Pi*scale*Pq/(qval*qval);            //this is now dimensionless...
1329       
1330        inten /= del;                   //normalize by the thickness (in A)
1331       
1332        inten *= 1.0e8;         // 1/A to 1/cm
1333       
1334        return(inten+bkg);
1335}
1336
1337/*      LamellarPSX  :  calculates the form factor of a lamellar structure - with S(q) effects included
1338--- now the proper resolution effects are used - the "default" resolution is turned off (= 0) and the
1339model is smeared just like any other function
1340*/
1341double
1342LamellarPS(double dp[], double q)
1343{
1344        double scale,dd,del,sig,contr,NN,Cp,bkg;                //local variables of coefficient wave
1345        double inten,qval,Pq,Sq,alpha,temp,t1,t2,t3,dQ;
1346        double Pi,Euler,dQDefault,fii,sldb,sld;
1347        int ii,NNint;
1348//      char buf[256];
1349
1350       
1351        Euler = 0.5772156649;           // Euler's constant
1352//      dQDefault = 0.0025;             //[=] 1/A, q-resolution, default value
1353        dQDefault = 0.0;
1354        dQ = dQDefault;
1355       
1356        Pi = 4.0*atan(1.0);
1357        qval = q;
1358       
1359        scale = dp[0];
1360        dd = dp[1];
1361        del = dp[2];
1362        sig = dp[3]*del;
1363        sldb = dp[4];
1364        sld = dp[5];
1365        contr = sldb - sld;
1366        NN = trunc(dp[6]);              //be sure that NN is an integer
1367        Cp = dp[7];
1368        bkg = dp[8];
1369       
1370        Pq = 2.0*contr*contr/qval/qval*(1.0-cos(qval*del)*exp(-0.5*qval*qval*sig*sig));
1371       
1372        NNint = (int)NN;                //cast to an integer for the loop
1373       
1374//      sprintf(buf, "qval = %g\r", qval);
1375//      XOPNotice(buf);
1376       
1377        ii=0;
1378        Sq = 0.0;
1379        for(ii=1;ii<(NNint-1);ii+=1) {
1380       
1381                fii = (double)ii;               //do I really need to do this?
1382               
1383                temp = 0.0;
1384                alpha = Cp/4.0/Pi/Pi*(log(Pi*fii) + Euler);
1385                t1 = 2.0*dQ*dQ*dd*dd*alpha;
1386                t2 = 2.0*qval*qval*dd*dd*alpha;
1387                t3 = dQ*dQ*dd*dd*fii*fii;
1388               
1389                temp = 1.0-fii/NN;
1390                temp *= cos(dd*qval*fii/(1.0+t1));
1391                temp *= exp(-1.0*(t2 + t3)/(2.0*(1.0+t1)) );
1392                temp /= sqrt(1.0+t1);
1393               
1394                Sq += temp;
1395        }
1396       
1397        Sq *= 2.0;
1398        Sq += 1.0;
1399       
1400        inten = 2.0*Pi*scale*Pq*Sq/(dd*qval*qval);
1401       
1402        inten *= 1.0e8;         // 1/A to 1/cm
1403       
1404    return(inten+bkg);
1405}
1406
1407
1408/*      LamellarPS_HGX  :  calculates the form factor of a lamellar structure - with S(q) effects included
1409--- now the proper resolution effects are used - the "default" resolution is turned off (= 0) and the
1410model is smeared just like any other function
1411*/
1412double
1413LamellarPS_HG(double dp[], double q)
1414{
1415        double scale,dd,delT,delH,SLD_T,SLD_H,SLD_S,NN,Cp,bkg;          //local variables of coefficient wave
1416        double inten,qval,Pq,Sq,alpha,temp,t1,t2,t3,dQ,drh,drt;
1417        double Pi,Euler,dQDefault,fii;
1418        int ii,NNint;
1419       
1420       
1421        Euler = 0.5772156649;           // Euler's constant
1422//      dQDefault = 0.0025;             //[=] 1/A, q-resolution, default value
1423        dQDefault = 0.0;
1424        dQ = dQDefault;
1425       
1426        Pi = 4.0*atan(1.0);
1427        qval= q;
1428       
1429        scale = dp[0];
1430        dd = dp[1];
1431        delT = dp[2];
1432        delH = dp[3];
1433        SLD_T = dp[4];
1434        SLD_H = dp[5];
1435        SLD_S = dp[6];
1436        NN = trunc(dp[7]);              //be sure that NN is an integer
1437        Cp = dp[8];
1438        bkg = dp[9];
1439       
1440       
1441        drh = SLD_H - SLD_S;
1442        drt = SLD_T - SLD_S;    //correction 13FEB06 by L.Porcar
1443       
1444        Pq = drh*(sin(qval*(delH+delT))-sin(qval*delT)) + drt*sin(qval*delT);
1445        Pq *= Pq;
1446        Pq *= 4.0/(qval*qval);
1447       
1448        NNint = (int)NN;                //cast to an integer for the loop
1449        ii=0;
1450        Sq = 0.0;
1451        for(ii=1;ii<(NNint-1);ii+=1) {
1452       
1453                fii = (double)ii;               //do I really need to do this?
1454               
1455                temp = 0.0;
1456                alpha = Cp/4.0/Pi/Pi*(log(Pi*ii) + Euler);
1457                t1 = 2.0*dQ*dQ*dd*dd*alpha;
1458                t2 = 2.0*qval*qval*dd*dd*alpha;
1459                t3 = dQ*dQ*dd*dd*ii*ii;
1460               
1461                temp = 1.0-ii/NN;
1462                temp *= cos(dd*qval*ii/(1.0+t1));
1463                temp *= exp(-1.0*(t2 + t3)/(2.0*(1.0+t1)) );
1464                temp /= sqrt(1.0+t1);
1465               
1466                Sq += temp;
1467        }
1468       
1469        Sq *= 2.0;
1470        Sq += 1.0;
1471       
1472        inten = 2.0*Pi*scale*Pq*Sq/(dd*qval*qval);
1473       
1474        inten *= 1.0e8;         // 1/A to 1/cm
1475       
1476        return(inten+bkg);
1477}
1478
1479/*      LamellarFF_HGX  :  calculates the form factor of a lamellar structure - no S(q) effects included
1480but extra SLD for head groups is included
1481
1482*/
1483double
1484LamellarFF_HG(double dp[], double q)
1485{
1486        double scale,delT,delH,slds,sldh,sldt,bkg;              //local variables of coefficient wave
1487        double inten, qval,Pq,drh,drt;
1488        double Pi;
1489       
1490       
1491        Pi = 4.0*atan(1.0);
1492        qval= q;
1493        scale = dp[0];
1494        delT = dp[1];
1495        delH = dp[2];
1496        sldt = dp[3];
1497        sldh = dp[4];
1498        slds = dp[5];
1499        bkg = dp[6];
1500       
1501       
1502        drh = sldh - slds;
1503        drt = sldt - slds;              //correction 13FEB06 by L.Porcar
1504       
1505        Pq = drh*(sin(qval*(delH+delT))-sin(qval*delT)) + drt*sin(qval*delT);
1506        Pq *= Pq;
1507        Pq *= 4.0/(qval*qval);
1508       
1509        inten = 2.0*Pi*scale*Pq/(qval*qval);            //dimensionless...
1510       
1511        inten /= 2.0*(delT+delH);                       //normalize by the bilayer thickness
1512       
1513        inten *= 1.0e8;         // 1/A to 1/cm
1514       
1515        return(inten+bkg);
1516}
1517
1518/*      FlexExclVolCylX  :  calculates the form factor of a flexible cylinder with a circular cross section
1519-- incorporates Wei-Ren Chen's fixes - 2006
1520
1521        */
1522double
1523FlexExclVolCyl(double dp[], double q)
1524{
1525        double scale,L,B,bkg,rad,qr,cont,sldc,slds;
1526        double Pi,flex,crossSect,answer;
1527       
1528       
1529        Pi = 4.0*atan(1.0);
1530       
1531        scale = dp[0];          //make local copies in case memory moves
1532        L = dp[1];
1533        B = dp[2];
1534        rad = dp[3];
1535        sldc = dp[4];
1536        slds = dp[5];
1537        cont = sldc-slds;
1538        bkg = dp[6];
1539       
1540   
1541        qr = q*rad;
1542       
1543        flex = Sk_WR(q,L,B);
1544       
1545        crossSect = (2.0*NR_BessJ1(qr)/qr)*(2.0*NR_BessJ1(qr)/qr);
1546        flex *= crossSect;
1547        flex *= Pi*rad*rad*L;
1548        flex *= cont*cont;
1549        flex *= 1.0e8;
1550        answer = scale*flex + bkg;
1551       
1552        return answer;
1553}
1554
1555/*      FlexCyl_EllipX  :  calculates the form factor of a flexible cylinder with an elliptical cross section
1556-- incorporates Wei-Ren Chen's fixes - 2006
1557
1558        */
1559double
1560FlexCyl_Ellip(double dp[], double q)
1561{
1562        double scale,L,B,bkg,rad,qr,cont,ellRatio,slds,sldc;
1563        double Pi,flex,crossSect,answer;
1564       
1565       
1566        Pi = 4.0*atan(1.0);
1567        scale = dp[0];          //make local copies in case memory moves
1568        L = dp[1];
1569        B = dp[2];
1570        rad = dp[3];
1571        ellRatio = dp[4];
1572        sldc = dp[5];
1573        slds = dp[6];
1574        bkg = dp[7];
1575       
1576        cont = sldc - slds;
1577        qr = q*rad;
1578       
1579        flex = Sk_WR(q,L,B);
1580       
1581        crossSect = EllipticalCross_fn(q,rad,(rad*ellRatio));
1582        flex *= crossSect;
1583        flex *= Pi*rad*rad*ellRatio*L;
1584        flex *= cont*cont;
1585        flex *= 1.0e8;
1586        answer = scale*flex + bkg;
1587       
1588        return answer;
1589}
1590
1591double
1592EllipticalCross_fn(double qq, double a, double b)
1593{
1594    double uplim,lolim,Pi,summ,arg,zi,yyy,answer;
1595    int i,nord=76;
1596   
1597    Pi = 4.0*atan(1.0);
1598    lolim=0.0;
1599    uplim=Pi/2.0;
1600    summ=0.0;
1601   
1602    for(i=0;i<nord;i++) {
1603                zi = ( Gauss76Z[i]*(uplim-lolim) + uplim + lolim )/2.0;
1604                arg = qq*sqrt(a*a*sin(zi)*sin(zi)+b*b*cos(zi)*cos(zi));
1605                yyy = pow((2.0 * NR_BessJ1(arg) / arg),2);
1606                yyy *= Gauss76Wt[i];
1607                summ += yyy;
1608    }
1609    answer = (uplim-lolim)/2.0*summ;
1610    answer *= 2.0/Pi;
1611    return(answer);
1612       
1613}
1614/*      FlexCyl_PolyLenX  :  calculates the form factor of a flecible cylinder at the given x-value p->x
1615the cylinder has a polydisperse Length
1616
1617*/
1618double
1619FlexCyl_PolyLen(double dp[], double q)
1620{
1621        int i;
1622        double scale,radius,length,pd,bkg,lb,delrho,sldc,slds;          //local variables of coefficient wave
1623        int nord=20;                    //order of integration
1624        double uplim,lolim;             //upper and lower integration limits
1625        double summ,zi,yyy,answer,Vpoly;                        //running tally of integration
1626        double range,zz,Pi;
1627       
1628        Pi = 4.0*atan(1.0);
1629        range = 3.4;
1630       
1631        summ = 0.0;                     //initialize intergral
1632        scale = dp[0];                  //make local copies in case memory moves
1633        length = dp[1];                 //radius
1634        pd = dp[2];                     // average length
1635        lb = dp[3];
1636        radius = dp[4];
1637        sldc = dp[5];
1638        slds = dp[6];
1639        bkg = dp[7];
1640       
1641        delrho = sldc - slds;
1642        zz = (1.0/pd)*(1.0/pd) - 1.0;
1643       
1644        lolim = length*(1.0-range*pd);          //set the upper/lower limits to cover the distribution
1645        if(lolim<0.0) {
1646                lolim = 0.0;
1647        }
1648        if(pd>0.3) {
1649                range = 3.4 + (pd-0.3)*18.0;
1650        }
1651        uplim = length*(1.0+range*pd);
1652       
1653        for(i=0;i<nord;i++) {
1654                zi = ( Gauss20Z[i]*(uplim-lolim) + uplim + lolim )/2.0;
1655                yyy = Gauss20Wt[i] * FlePolyLen_kernel(q,radius,length,lb,zz,delrho,zi);
1656                summ += yyy;
1657        }
1658       
1659        answer = (uplim-lolim)/2.0*summ;
1660        //normalize by average cylinder volume (first moment), using the average length
1661        Vpoly=Pi*radius*radius*length;
1662        answer /= Vpoly;
1663       
1664        answer *=delrho*delrho;
1665       
1666        //convert to [cm-1]
1667        answer *= 1.0e8;
1668        //Scale
1669        answer *= scale;
1670        // add in the background
1671        answer += bkg;
1672       
1673        return answer;
1674}
1675
1676/*      FlexCyl_PolyLenX  :  calculates the form factor of a flexible cylinder at the given x-value p->x
1677the cylinder has a polydisperse cross sectional radius
1678
1679*/
1680double
1681FlexCyl_PolyRad(double dp[], double q)
1682{
1683        int i;
1684        double scale,radius,length,pd,delrho,bkg,lb,sldc,slds;          //local variables of coefficient wave
1685        int nord=76;                    //order of integration
1686        double uplim,lolim;             //upper and lower integration limits
1687        double summ,zi,yyy,answer,Vpoly;                        //running tally of integration
1688        double range,zz,Pi;
1689       
1690       
1691        Pi = 4.0*atan(1.0);
1692        range = 3.4;
1693       
1694        summ = 0.0;                     //initialize intergral
1695       
1696        scale = dp[0];                  //make local copies in case memory moves
1697        length = dp[1];                 //radius
1698        lb = dp[2];                     // average length
1699        radius = dp[3];
1700        pd = dp[4];
1701        sldc = dp[5];
1702        slds = dp[6];
1703        bkg = dp[7];
1704       
1705        delrho = sldc-slds;
1706        zz = (1.0/pd)*(1.0/pd) - 1.0;
1707       
1708        lolim = radius*(1.0-range*pd);          //set the upper/lower limits to cover the distribution
1709        if(lolim<0.0) {
1710                lolim = 0.0;
1711        }
1712        if(pd>0.3) {
1713                range = 3.4 + (pd-0.3)*18.0;
1714        }
1715        uplim = radius*(1.0+range*pd);
1716       
1717        for(i=0;i<nord;i++) {
1718                //zi = ( Gauss20Z[i]*(uplim-lolim) + uplim + lolim )/2.0;
1719                //yyy = Gauss20Wt[i] * FlePolyRad_kernel(q,radius,length,lb,zz,delrho,zi);
1720                zi = ( Gauss76Z[i]*(uplim-lolim) + uplim + lolim )/2.0;
1721                yyy = Gauss76Wt[i] * FlePolyRad_kernel(q,radius,length,lb,zz,delrho,zi);
1722                summ += yyy;
1723        }
1724       
1725        answer = (uplim-lolim)/2.0*summ;
1726        //normalize by average cylinder volume (second moment), using the average radius
1727        Vpoly = Pi*radius*radius*length*(zz+2.0)/(zz+1.0);
1728        answer /= Vpoly;
1729       
1730        answer *=delrho*delrho;
1731       
1732        //convert to [cm-1]
1733        answer *= 1.0e8;
1734        //Scale
1735        answer *= scale;
1736        // add in the background
1737        answer += bkg;
1738       
1739        return answer;
1740}
1741
1742
1743
1744///////////////
1745
1746//
1747//     FUNCTION gfn2:    CONTAINS F(Q,A,B,mu)**2  AS GIVEN
1748//                       BY (53) AND (56,57) IN CHEN AND
1749//                       KOTLARCHYK REFERENCE
1750//
1751//     <PROLATE ELLIPSOIDS>
1752//
1753double
1754gfn2(double xx, double crmaj, double crmin, double trmaj, double trmin, double delpc, double delps, double qq)
1755{
1756        // local variables
1757        double aa,bb,u2,ut2,uq,ut,vc,vt,siq,sit,gfnc,gfnt,gfn2,pi43,gfn,Pi;
1758
1759        Pi = 4.0*atan(1.0);
1760       
1761        pi43=4.0/3.0*Pi;
1762        aa = crmaj;
1763        bb = crmin;
1764        u2 = (aa*aa*xx*xx + bb*bb*(1.0-xx*xx));
1765        ut2 = (trmaj*trmaj*xx*xx + trmin*trmin*(1.0-xx*xx));
1766        uq = sqrt(u2)*qq;
1767        ut= sqrt(ut2)*qq;
1768        vc = pi43*aa*bb*bb;
1769        vt = pi43*trmaj*trmin*trmin;
1770        if (uq == 0.0){
1771                siq = 1.0/3.0;
1772        }else{
1773                siq = (sin(uq)/uq/uq - cos(uq)/uq)/uq;
1774        }
1775        if (ut == 0.0){
1776                sit = 1.0/3.0;
1777        }else{
1778                sit = (sin(ut)/ut/ut - cos(ut)/ut)/ut;
1779        }
1780        gfnc = 3.0*siq*vc*delpc;
1781        gfnt = 3.0*sit*vt*delps;
1782        gfn = gfnc+gfnt;
1783        gfn2 = gfn*gfn;
1784       
1785        return (gfn2);
1786}
1787
1788//
1789//     FUNCTION gfn4:    CONTAINS F(Q,A,B,MU)**2  AS GIVEN
1790//                       BY (53) & (58-59) IN CHEN AND
1791//                       KOTLARCHYK REFERENCE
1792//
1793//       <OBLATE ELLIPSOID>
1794// function gfn4 for oblate ellipsoids
1795double
1796gfn4(double xx, double crmaj, double crmin, double trmaj, double trmin, double delpc, double delps, double qq)
1797{
1798        // local variables
1799        double aa,bb,u2,ut2,uq,ut,vc,vt,siq,sit,gfnc,gfnt,tgfn,gfn4,pi43,Pi;
1800
1801        Pi = 4.0*atan(1.0);
1802        pi43=4.0/3.0*Pi;
1803        aa = crmaj;
1804        bb = crmin;
1805        u2 = (bb*bb*xx*xx + aa*aa*(1.0-xx*xx));
1806        ut2 = (trmin*trmin*xx*xx + trmaj*trmaj*(1.0-xx*xx));
1807        uq = sqrt(u2)*qq;
1808        ut= sqrt(ut2)*qq;
1809        vc = pi43*aa*aa*bb;
1810        vt = pi43*trmaj*trmaj*trmin;
1811        if (uq == 0.0){
1812                siq = 1.0/3.0;
1813        }else{
1814                siq = (sin(uq)/uq/uq - cos(uq)/uq)/uq;
1815        }
1816        if (ut == 0.0){
1817                sit = 1.0/3.0;
1818        }else{
1819                sit = (sin(ut)/ut/ut - cos(ut)/ut)/ut;
1820        }
1821        gfnc = 3.0*siq*vc*delpc;
1822        gfnt = 3.0*sit*vt*delps;
1823        tgfn = gfnc+gfnt;
1824        gfn4 = tgfn*tgfn;
1825       
1826        return (gfn4);
1827}
1828
1829double
1830FlePolyLen_kernel(double q, double radius, double length, double lb, double zz, double delrho, double zi)
1831{
1832    double Pq,vcyl,dl;
1833    double Pi,qr;
1834   
1835    Pi = 4.0*atan(1.0);
1836    qr = q*radius;
1837   
1838    Pq = Sk_WR(q,zi,lb);                //does not have cross section term
1839    if (qr !=0){
1840        Pq *= (2.0*NR_BessJ1(qr)/qr)*(2.0*NR_BessJ1(qr)/qr);
1841    } 
1842    vcyl=Pi*radius*radius*zi;
1843    Pq *= vcyl*vcyl;
1844   
1845    dl = SchulzPoint_cpr(zi,length,zz);
1846    return (Pq*dl);     
1847       
1848}
1849
1850double
1851FlePolyRad_kernel(double q, double ravg, double Lc, double Lb, double zz, double delrho, double zi)
1852{
1853    double Pq,vcyl,dr;
1854    double Pi,qr;
1855   
1856    Pi = 4.0*atan(1.0);
1857    qr = q*zi;
1858   
1859    Pq = Sk_WR(q,Lc,Lb);                //does not have cross section term
1860    if (qr !=0){
1861        Pq *= (2.0*NR_BessJ1(qr)/qr)*(2.0*NR_BessJ1(qr)/qr);
1862    }
1863
1864    vcyl=Pi*zi*zi*Lc;
1865    Pq *= vcyl*vcyl;
1866   
1867    dr = SchulzPoint_cpr(zi,ravg,zz);
1868    return (Pq*dr);     
1869       
1870}
1871
1872double
1873CSCylIntegration(double qq, double rad, double radthick, double facthick, double rhoc, double rhos, double rhosolv, double length)
1874{
1875        double answer,halfheight,Pi;
1876        double lolim,uplim,summ,yyy,zi;
1877        int nord,i;
1878       
1879        // set up the integration end points
1880        Pi = 4.0*atan(1.0);
1881        nord = 76;
1882        lolim = 0.0;
1883        uplim = Pi/2.0;
1884        halfheight = length/2.0;
1885       
1886        summ = 0.0;                             // initialize integral
1887        i=0;
1888        for(i=0;i<nord;i++) {
1889                zi = ( Gauss76Z[i]*(uplim-lolim) + uplim + lolim )/2.0;
1890                yyy = Gauss76Wt[i] * CScyl(qq, rad, radthick, facthick, rhoc,rhos,rhosolv, halfheight, zi);
1891                summ += yyy;
1892        }
1893       
1894        // calculate value of integral to return
1895        answer = (uplim-lolim)/2.0*summ;
1896        return (answer);
1897}
1898
1899double
1900CScyl(double qq, double rad, double radthick, double facthick, double rhoc, double rhos, double rhosolv, double length, double dum)
1901{       
1902        // qq is the q-value for the calculation (1/A)
1903        // radius is the core radius of the cylinder (A)
1904        //  radthick and facthick are the radial and face layer thicknesses
1905        // rho(n) are the respective SLD's
1906        // length is the *Half* CORE-LENGTH of the cylinder
1907        // dum is the dummy variable for the integration (theta)
1908
1909        double dr1,dr2,besarg1,besarg2,vol1,vol2,sinarg1,sinarg2,si1,si2,be1,be2,t1,t2,retval;
1910        double Pi;
1911       
1912        Pi = 4.0*atan(1.0); 
1913       
1914        dr1 = rhoc-rhos;
1915        dr2 = rhos-rhosolv;
1916        vol1 = Pi*rad*rad*(2.0*length);
1917        vol2 = Pi*(rad+radthick)*(rad+radthick)*(2.0*length+2.0*facthick);
1918       
1919        besarg1 = qq*rad*sin(dum);
1920        besarg2 = qq*(rad+radthick)*sin(dum);
1921        sinarg1 = qq*length*cos(dum);
1922        sinarg2 = qq*(length+facthick)*cos(dum);
1923        if (besarg1 == 0.0){
1924                be1 = 0.5;
1925        }else{
1926                be1 = NR_BessJ1(besarg1)/besarg1;
1927        }
1928        if (besarg2 == 0.0){
1929                be2 = 0.5;
1930        }else{
1931                be2 = NR_BessJ1(besarg2)/besarg2;
1932        }
1933        if (sinarg1 == 0.0){
1934                si1 = 1.0;
1935        }else{
1936                si1 = sin(sinarg1)/sinarg1;
1937        }
1938        if (sinarg2 == 0.0){
1939                si2 = 1.0;
1940        }else{
1941                si2 = sin(sinarg2)/sinarg2;
1942        }
1943
1944        t1 = 2.0*vol1*dr1*si1*be1;
1945        t2 = 2.0*vol2*dr2*si2*be2;
1946
1947        retval = ((t1+t2)*(t1+t2))*sin(dum);
1948        return (retval);
1949   
1950}
1951
1952
1953double
1954CoreShellCylKernel(double qq, double rcore, double thick, double rhoc, double rhos, double rhosolv, double length, double dum)
1955{
1956
1957    double dr1,dr2,besarg1,besarg2,vol1,vol2,sinarg1,sinarg2,si1,si2,be1,be2,t1,t2,retval;
1958    double Pi;
1959   
1960    Pi = 4.0*atan(1.0);
1961   
1962    dr1 = rhoc-rhos;
1963    dr2 = rhos-rhosolv;
1964    vol1 = Pi*rcore*rcore*(2.0*length);
1965    vol2 = Pi*(rcore+thick)*(rcore+thick)*(2.0*length+2.0*thick);
1966   
1967    besarg1 = qq*rcore*sin(dum);
1968    besarg2 = qq*(rcore+thick)*sin(dum);
1969    sinarg1 = qq*length*cos(dum);
1970    sinarg2 = qq*(length+thick)*cos(dum);
1971
1972        if (besarg1 == 0.0){
1973                be1 = 0.5;
1974        }else{
1975                be1 = NR_BessJ1(besarg1)/besarg1;
1976        }
1977        if (besarg2 == 0.0){
1978                be2 = 0.5;
1979        }else{
1980                be2 = NR_BessJ1(besarg2)/besarg2;
1981        }
1982        if (sinarg1 == 0.0){
1983                si1 = 1.0;
1984        }else{
1985                si1 = sin(sinarg1)/sinarg1;
1986        }
1987        if (sinarg2 == 0.0){
1988                si2 = 1.0;
1989        }else{
1990                si2 = sin(sinarg2)/sinarg2;
1991        }
1992
1993    t1 = 2.0*vol1*dr1*si1*be1;
1994    t2 = 2.0*vol2*dr2*si2*be2;
1995
1996    retval = ((t1+t2)*(t1+t2))*sin(dum);
1997       
1998    return (retval);
1999}
2000
2001double
2002Cyl_PolyLenKernel(double q, double radius, double len_avg, double zz, double delrho, double dumLen)
2003{
2004       
2005    double halfheight,uplim,lolim,zi,summ,yyy,Pi;
2006    double answer,dr,Vcyl;
2007    int i,nord;
2008   
2009    Pi = 4.0*atan(1.0);
2010    lolim = 0.0;
2011    uplim = Pi/2.0;
2012    halfheight = dumLen/2.0;
2013    nord=20;
2014    summ = 0.0;
2015   
2016    //do the cylinder orientational average
2017    for(i=0;i<nord;i++) {
2018                zi = ( Gauss20Z[i]*(uplim-lolim) + uplim + lolim )/2.0;
2019                yyy = Gauss20Wt[i] * CylKernel(q, radius, halfheight, zi);
2020                summ += yyy;
2021    }
2022    answer = (uplim-lolim)/2.0*summ;
2023    // Multiply by contrast^2
2024    answer *= delrho*delrho;
2025    // don't do the normal scaling to volume here
2026    // instead, multiply by VCyl^2 to get rid of the normalization for this radius of cylinder
2027    Vcyl = Pi*radius*radius*dumLen;
2028    answer *= Vcyl*Vcyl;
2029   
2030    dr = SchulzPoint_cpr(dumLen,len_avg,zz);
2031    return(dr*answer);
2032}
2033
2034
2035double
2036Stackdisc_kern(double qq, double rcore, double rhoc, double rhol, double rhosolv, double length, double thick, double dum, double gsd, double d, double N)
2037{               
2038        // qq is the q-value for the calculation (1/A)
2039        // rcore is the core radius of the cylinder (A)
2040        // rho(n) are the respective SLD's
2041        // length is the *Half* CORE-LENGTH of the cylinder = L (A)
2042        // dum is the dummy variable for the integration (x in Feigin's notation)
2043
2044        //Local variables
2045        double totald,dr1,dr2,besarg1,besarg2,be1,be2,si1,si2,area,sinarg1,sinarg2,t1,t2,retval,sqq,dexpt;
2046        double Pi;
2047        int kk;
2048       
2049        Pi = 4.0*atan(1.0);
2050       
2051        dr1 = rhoc-rhosolv;
2052        dr2 = rhol-rhosolv;
2053        area = Pi*rcore*rcore;
2054        totald=2.0*(thick+length);
2055       
2056        besarg1 = qq*rcore*sin(dum);
2057        besarg2 = qq*rcore*sin(dum);
2058       
2059        sinarg1 = qq*length*cos(dum);
2060        sinarg2 = qq*(length+thick)*cos(dum);
2061
2062        if (besarg1 == 0.0){
2063                be1 = 0.5;
2064        }else{
2065                be1 = NR_BessJ1(besarg1)/besarg1;
2066        }
2067        if (besarg2 == 0.0){
2068                be2 = 0.5;
2069        }else{
2070                be2 = NR_BessJ1(besarg2)/besarg2;
2071        }
2072        if (sinarg1 == 0.0){
2073                si1 = 1.0;
2074        }else{
2075                si1 = sin(sinarg1)/sinarg1;
2076        }
2077        if (sinarg2 == 0.0){
2078                si2 = 1.0;
2079        }else{
2080                si2 = sin(sinarg2)/sinarg2;
2081        }
2082
2083        t1 = 2.0*area*(2.0*length)*dr1*(si1)*(be1);
2084        t2 = 2.0*area*dr2*(totald*si2-2.0*length*si1)*(be2);
2085
2086        retval =((t1+t2)*(t1+t2))*sin(dum);
2087       
2088        // loop for the structure facture S(q)
2089        sqq=0.0;
2090        for(kk=1;kk<N;kk+=1) {
2091                dexpt=qq*cos(dum)*qq*cos(dum)*d*d*gsd*gsd*kk/2.0;
2092                sqq=sqq+(N-kk)*cos(qq*cos(dum)*d*kk)*exp(-1.*dexpt);
2093        }                       
2094       
2095        // end of loop for S(q)
2096        sqq=1.0+2.0*sqq/N;
2097        retval *= sqq;
2098   
2099        return(retval);
2100}
2101
2102
2103double
2104Cyl_PolyRadKernel(double q, double radius, double length, double zz, double delrho, double dumRad)
2105{
2106       
2107    double halfheight,uplim,lolim,zi,summ,yyy,Pi;
2108    double answer,dr,Vcyl;
2109    int i,nord;
2110   
2111    Pi = 4.0*atan(1.0);
2112    lolim = 0.0;
2113    uplim = Pi/2.0;
2114    halfheight = length/2.0;
2115        //    nord=20;
2116    nord=76;
2117    summ = 0.0;
2118   
2119    //do the cylinder orientational average
2120        //    for(i=0;i<nord;i++) {
2121        //            zi = ( Gauss20Z[i]*(uplim-lolim) + uplim + lolim )/2.0;
2122        //            yyy = Gauss20Wt[i] * CylKernel(q, dumRad, halfheight, zi);
2123        //            summ += yyy;
2124        //    }
2125    for(i=0;i<nord;i++) {
2126                zi = ( Gauss76Z[i]*(uplim-lolim) + uplim + lolim )/2.0;
2127                yyy = Gauss76Wt[i] * CylKernel(q, dumRad, halfheight, zi);
2128                summ += yyy;
2129    }
2130    answer = (uplim-lolim)/2.0*summ;
2131    // Multiply by contrast^2
2132    answer *= delrho*delrho;
2133    // don't do the normal scaling to volume here
2134    // instead, multiply by VCyl^2 to get rid of the normalization for this radius of cylinder
2135    Vcyl = Pi*dumRad*dumRad*length;
2136    answer *= Vcyl*Vcyl;
2137   
2138    dr = SchulzPoint_cpr(dumRad,radius,zz);
2139    return(dr*answer);
2140}
2141
2142double
2143SchulzPoint_cpr(double dumRad, double radius, double zz)
2144{
2145    double dr;
2146   
2147    dr = zz*log(dumRad) - gammaln(zz+1.0) + (zz+1.0)*log((zz+1.0)/radius)-(dumRad/radius*(zz+1.0));
2148    return(exp(dr));
2149}
2150
2151
2152double
2153EllipsoidKernel(double qq, double a, double nua, double dum)
2154{
2155    double arg,nu,retval;               //local variables
2156       
2157    nu = nua/a;
2158    arg = qq*a*sqrt(1.0+dum*dum*(nu*nu-1.0));
2159    if (arg == 0.0){
2160        retval =1.0/3.0;
2161    }else{
2162        retval = (sin(arg)-arg*cos(arg))/(arg*arg*arg);
2163    }
2164    retval *= retval;
2165    retval *= 9.0;
2166
2167    return(retval);
2168}//Function EllipsoidKernel()
2169
2170double
2171HolCylKernel(double qq, double rcore, double rshell, double length, double dum)
2172{
2173    double gamma,arg1,arg2,lam1,lam2,psi,sinarg,t2,retval;              //local variables
2174   
2175    gamma = rcore/rshell;
2176    arg1 = qq*rshell*sqrt(1.0-dum*dum);         //1=shell (outer radius)
2177    arg2 = qq*rcore*sqrt(1.0-dum*dum);                  //2=core (inner radius)
2178    if (arg1 == 0.0){
2179        lam1 = 1.0;
2180    }else{
2181        lam1 = 2.0*NR_BessJ1(arg1)/arg1;
2182    }
2183    if (arg2 == 0.0){
2184        lam2 = 1.0;
2185    }else{
2186        lam2 = 2.0*NR_BessJ1(arg2)/arg2;
2187    }
2188    //Todo: Need to check psi behavior as gamma goes to 1.
2189    psi = 1.0/(1.0-gamma*gamma)*(lam1 -  gamma*gamma*lam2);             //SRK 10/19/00
2190    sinarg = qq*length*dum/2.0;
2191    if (sinarg == 0.0){
2192        t2 = 1.0;
2193    }else{
2194        t2 = sin(sinarg)/sinarg;
2195    }
2196
2197    retval = psi*psi*t2*t2;
2198   
2199    return(retval);
2200}//Function HolCylKernel()
2201
2202double
2203PPKernel(double aa, double mu, double uu)
2204{
2205    // mu passed in is really mu*sqrt(1-sig^2)
2206    double arg1,arg2,Pi,tmp1,tmp2;                      //local variables
2207       
2208    Pi = 4.0*atan(1.0);
2209   
2210    //handle arg=0 separately, as sin(t)/t -> 1 as t->0
2211    arg1 = (mu/2.0)*cos(Pi*uu/2.0);
2212    arg2 = (mu*aa/2.0)*sin(Pi*uu/2.0);
2213    if(arg1==0.0) {
2214                tmp1 = 1.0;
2215        } else {
2216                tmp1 = sin(arg1)*sin(arg1)/arg1/arg1;
2217    }
2218
2219    if (arg2==0.0) {
2220                tmp2 = 1.0;
2221        } else {
2222                tmp2 = sin(arg2)*sin(arg2)/arg2/arg2;
2223    }
2224       
2225    return (tmp1*tmp2);
2226       
2227}//Function PPKernel()
2228
2229
2230double
2231TriaxialKernel(double q, double aa, double bb, double cc, double dx, double dy)
2232{
2233       
2234    double arg,val,pi;                  //local variables
2235       
2236    pi = 4.0*atan(1.0);
2237   
2238    arg = aa*aa*cos(pi*dx/2)*cos(pi*dx/2);
2239    arg += bb*bb*sin(pi*dx/2)*sin(pi*dx/2)*(1-dy*dy);
2240    arg += cc*cc*dy*dy;
2241    arg = q*sqrt(arg);
2242    if (arg == 0.0){
2243        val = 1.0; // as arg --> 0, val should go to 1.0
2244    }else{
2245        val = 9.0 * ( (sin(arg) - arg*cos(arg))/(arg*arg*arg) ) * ( (sin(arg) - arg*cos(arg))/(arg*arg*arg) );
2246    }
2247    return (val);
2248       
2249}//Function TriaxialKernel()
2250
2251
2252double
2253CylKernel(double qq, double rr,double h, double theta)
2254{
2255       
2256        // qq is the q-value for the calculation (1/A)
2257        // rr is the radius of the cylinder (A)
2258        // h is the HALF-LENGTH of the cylinder = L/2 (A)
2259
2260    double besarg,bj,retval,d1,t1,b1,t2,b2,siarg,be,si;          //Local variables
2261
2262
2263    besarg = qq*rr*sin(theta);
2264    siarg = qq * h * cos(theta);
2265    bj =NR_BessJ1(besarg);
2266       
2267        //* Computing 2nd power */
2268    d1 = sin(siarg);
2269    t1 = d1 * d1;
2270        //* Computing 2nd power */
2271    d1 = bj;
2272    t2 = d1 * d1 * 4.0 * sin(theta);
2273        //* Computing 2nd power */
2274    d1 = siarg;
2275    b1 = d1 * d1;
2276        //* Computing 2nd power */
2277    d1 = qq * rr * sin(theta);
2278    b2 = d1 * d1;
2279    if (besarg == 0.0){
2280        be = sin(theta);
2281    }else{
2282        be = t2 / b2;
2283    }
2284    if (siarg == 0.0){
2285        si = 1.0;
2286    }else{
2287        si = t1 / b1;
2288    }
2289    retval = be * si;
2290
2291    return (retval);
2292       
2293}//Function CylKernel()
2294
2295double
2296EllipCylKernel(double qq, double ra,double nu, double theta)
2297{
2298        //this is the function LAMBDA1^2 in Feigin's notation   
2299        // qq is the q-value for the calculation (1/A)
2300        // ra is the transformed radius"a" in Feigin's notation
2301        // nu is the ratio (major radius)/(minor radius) of the Ellipsoid [=] ---
2302        // theta is the dummy variable of the integration
2303       
2304        double retval,arg;               //Local variables
2305       
2306        arg = qq*ra*sqrt((1.0+nu*nu)/2+(1.0-nu*nu)*cos(theta)/2);
2307        if (arg == 0.0){
2308                retval = 1.0;
2309        }else{
2310                retval = 2.0*NR_BessJ1(arg)/arg;
2311        }
2312
2313        //square it
2314        retval *= retval;
2315       
2316    return(retval);
2317       
2318}//Function EllipCylKernel()
2319
2320double NR_BessJ1(double x)
2321{
2322        double ax,z;
2323        double xx,y,ans,ans1,ans2;
2324       
2325        if ((ax=fabs(x)) < 8.0) {
2326                y=x*x;
2327                ans1=x*(72362614232.0+y*(-7895059235.0+y*(242396853.1
2328                                                                                                  +y*(-2972611.439+y*(15704.48260+y*(-30.16036606))))));
2329                ans2=144725228442.0+y*(2300535178.0+y*(18583304.74
2330                                                                                           +y*(99447.43394+y*(376.9991397+y*1.0))));
2331                ans=ans1/ans2;
2332        } else {
2333                z=8.0/ax;
2334                y=z*z;
2335                xx=ax-2.356194491;
2336                ans1=1.0+y*(0.183105e-2+y*(-0.3516396496e-4
2337                                                                   +y*(0.2457520174e-5+y*(-0.240337019e-6))));
2338                ans2=0.04687499995+y*(-0.2002690873e-3
2339                                                          +y*(0.8449199096e-5+y*(-0.88228987e-6
2340                                                                                                         +y*0.105787412e-6)));
2341                ans=sqrt(0.636619772/ax)*(cos(xx)*ans1-z*sin(xx)*ans2);
2342                if (x < 0.0) ans = -ans;
2343        }
2344       
2345        return(ans);
2346}
2347
2348/*      Lamellar_ParaCrystal - Pedersen's model
2349
2350*/
2351double
2352Lamellar_ParaCrystal(double w[], double q)
2353{
2354//       Input (fitting) variables are:
2355        //[0] scale factor
2356        //[1]   thickness
2357        //[2]   number of layers
2358        //[3]   spacing between layers
2359        //[4]   polydispersity of spacing
2360        //[5] SLD lamellar
2361        //[6] SLD solvent
2362        //[7] incoherent background
2363//      give them nice names
2364        double inten,qval,scale,th,nl,davg,pd,contr,bkg,xn;
2365        double xi,ww,Pbil,Znq,Snq,an,sldLayer,sldSolvent,pi;
2366        long n1,n2;
2367       
2368        pi = 4.0*atan(1.0);
2369        scale = w[0];
2370        th = w[1];
2371        nl = w[2];
2372        davg = w[3];
2373        pd = w[4];
2374        sldLayer = w[5];
2375        sldSolvent = w[6];
2376        bkg = w[7];
2377       
2378        contr = w[5] - w[6];
2379        qval = q;
2380               
2381        //get the fractional part of nl, to determine the "mixing" of N's
2382       
2383        n1 = trunc(nl);         //rounds towards zero
2384        n2 = n1 + 1;
2385        xn = (double)n2 - nl;                   //fractional contribution of n1
2386       
2387        ww = exp(-qval*qval*pd*pd*davg*davg/2.0);
2388       
2389        //calculate the n1 contribution
2390        an = paraCryst_an(ww,qval,davg,n1);
2391        Snq = paraCryst_sn(ww,qval,davg,n1,an);
2392       
2393        Znq = xn*Snq;
2394       
2395        //calculate the n2 contribution
2396        an = paraCryst_an(ww,qval,davg,n2);
2397        Snq = paraCryst_sn(ww,qval,davg,n2,an);
2398       
2399        Znq += (1.0-xn)*Snq;
2400       
2401        //and the independent contribution
2402        Znq += (1.0-ww*ww)/(1.0+ww*ww-2.0*ww*cos(qval*davg));
2403       
2404        //the limit when NL approaches infinity
2405//      Zq = (1-ww^2)/(1+ww^2-2*ww*cos(qval*davg))
2406       
2407        xi = th/2.0;            //use 1/2 the bilayer thickness
2408        Pbil = (sin(qval*xi)/(qval*xi))*(sin(qval*xi)/(qval*xi));
2409       
2410        inten = 2.0*pi*contr*contr*Pbil*Znq/(qval*qval);
2411        inten *= 1.0e8;
2412       
2413        return(scale*inten+bkg);
2414}
2415
2416// functions for the lamellar paracrystal model
2417double
2418paraCryst_sn(double ww, double qval, double davg, long nl, double an) {
2419       
2420        double Snq;
2421       
2422        Snq = an/( (double)nl*pow((1.0+ww*ww-2.0*ww*cos(qval*davg)),2) );
2423       
2424        return(Snq);
2425}
2426
2427
2428double
2429paraCryst_an(double ww, double qval, double davg, long nl) {
2430       
2431        double an;
2432       
2433        an = 4.0*ww*ww - 2.0*(ww*ww*ww+ww)*cos(qval*davg);
2434        an -= 4.0*pow(ww,(nl+2))*cos((double)nl*qval*davg);
2435        an += 2.0*pow(ww,(nl+3))*cos((double)(nl-1)*qval*davg);
2436        an += 2.0*pow(ww,(nl+1))*cos((double)(nl+1)*qval*davg);
2437       
2438        return(an);
2439}
2440
2441
2442/*      Spherocylinder  :
2443
2444Uses 76 pt Gaussian quadrature for both integrals
2445*/
2446double
2447Spherocylinder(double w[], double x)
2448{
2449        int i,j;
2450        double Pi;
2451        double scale,contr,bkg,sldc,slds;
2452        double len,rad,hDist,endRad;
2453        int nordi=76;                   //order of integration
2454        int nordj=76;
2455        double va,vb;           //upper and lower integration limits
2456        double summ,zi,yyy,answer;                      //running tally of integration
2457        double summj,vaj,vbj,zij;                       //for the inner integration
2458        double SphCyl_tmp[7],arg1,arg2,inner,be;
2459       
2460       
2461        scale = w[0];
2462        rad = w[1];
2463        len = w[2];
2464        sldc = w[3];
2465        slds = w[4];
2466        bkg = w[5];
2467       
2468        SphCyl_tmp[0] = w[0];
2469        SphCyl_tmp[1] = w[1];
2470        SphCyl_tmp[2] = w[2];
2471        SphCyl_tmp[3] = w[1];           //end radius is same as cylinder radius
2472        SphCyl_tmp[4] = w[3];
2473        SphCyl_tmp[5] = w[4];
2474        SphCyl_tmp[6] = w[5];
2475       
2476        hDist = 0;              //by definition for this model
2477        endRad = rad;
2478       
2479        contr = sldc-slds;
2480       
2481        Pi = 4.0*atan(1.0);
2482        va = 0.0;
2483        vb = Pi/2.0;            //orintational average, outer integral
2484        vaj = -1.0*hDist/endRad;
2485        vbj = 1.0;              //endpoints of inner integral
2486
2487        summ = 0.0;                     //initialize intergral
2488
2489        for(i=0;i<nordi;i++) {
2490                //setup inner integral over the ellipsoidal cross-section
2491                summj=0.0;
2492                zi = ( Gauss76Z[i]*(vb-va) + va + vb )/2.0;             //the "theta" dummy
2493               
2494                for(j=0;j<nordj;j++) {
2495                        //20 gauss points for the inner integral
2496                        zij = ( Gauss76Z[j]*(vbj-vaj) + vaj + vbj )/2.0;                //the "t" dummy
2497                        yyy = Gauss76Wt[j] * SphCyl_kernel(SphCyl_tmp,x,zij,zi);
2498                        summj += yyy;
2499                }
2500                //now calculate the value of the inner integral
2501                inner = (vbj-vaj)/2.0*summj;
2502                inner *= 4.0*Pi*endRad*endRad*endRad;
2503               
2504                //now calculate outer integrand
2505                arg1 = x*len/2.0*cos(zi);
2506                arg2 = x*rad*sin(zi);
2507                yyy = inner;
2508
2509                if(arg2 == 0) {
2510                        be = 0.5;
2511                } else {
2512                        be = NR_BessJ1(arg2)/arg2;
2513                }
2514               
2515                if(arg1 == 0.0) {               //limiting value of sinc(0) is 1; sinc is not defined in math.h
2516                        yyy += Pi*rad*rad*len*2.0*be;
2517                } else {
2518                        yyy += Pi*rad*rad*len*sin(arg1)/arg1*2.0*be;
2519                }
2520                yyy *= yyy;
2521                yyy *= sin(zi);         // = |A(q)|^2*sin(theta)
2522                yyy *= Gauss76Wt[i];
2523                summ += yyy;
2524        }               //final scaling is done at the end of the function, after the NT_FP64 case
2525       
2526        answer = (vb-va)/2.0*summ;
2527
2528        answer /= Pi*rad*rad*len + Pi*4.0*endRad*endRad*endRad/3.0;             //divide by volume
2529        answer *= 1.0e8;                //convert to cm^-1
2530        answer *= contr*contr;
2531        answer *= scale;
2532        answer += bkg;
2533               
2534        return answer;
2535}
2536
2537
2538// inner integral of the sphereocylinder model, special case of hDist = 0
2539//
2540double
2541SphCyl_kernel(double w[], double x, double tt, double theta) {
2542
2543        double val,arg1,arg2;
2544        double scale,bkg,sldc,slds;
2545        double len,rad,hDist,endRad,be;
2546        scale = w[0];
2547        rad = w[1];
2548        len = w[2];
2549        endRad = w[3];
2550        sldc = w[4];
2551        slds = w[5];
2552        bkg = w[6];
2553       
2554        hDist = 0.0;
2555               
2556        arg1 = x*cos(theta)*(endRad*tt+hDist+len/2.0);
2557        arg2 = x*endRad*sin(theta)*sqrt(1.0-tt*tt);
2558       
2559        if(arg2 == 0) {
2560                be = 0.5;
2561        } else {
2562                be = NR_BessJ1(arg2)/arg2;
2563        }
2564        val = cos(arg1)*(1.0-tt*tt)*be;
2565       
2566        return(val);
2567}
2568
2569
2570/*      Convex Lens  : special case where L ~ 0 and hDist < 0
2571
2572Uses 76 pt Gaussian quadrature for both integrals
2573*/
2574double
2575ConvexLens(double w[], double x)
2576{
2577        int i,j;
2578        double Pi;
2579        double scale,contr,bkg,sldc,slds;
2580        double len,rad,hDist,endRad;
2581        int nordi=76;                   //order of integration
2582        int nordj=76;
2583        double va,vb;           //upper and lower integration limits
2584        double summ,zi,yyy,answer;                      //running tally of integration
2585        double summj,vaj,vbj,zij;                       //for the inner integration
2586        double CLens_tmp[7],arg1,arg2,inner,hh,be;
2587       
2588       
2589        scale = w[0];
2590        rad = w[1];
2591//      len = w[2]
2592        endRad = w[2];
2593        sldc = w[3];
2594        slds = w[4];
2595        bkg = w[5];
2596       
2597        len = 0.01;
2598       
2599        CLens_tmp[0] = w[0];
2600        CLens_tmp[1] = w[1];
2601        CLens_tmp[2] = len;                     //length is some small number, essentially zero
2602        CLens_tmp[3] = w[2];
2603        CLens_tmp[4] = w[3];
2604        CLens_tmp[5] = w[4];
2605        CLens_tmp[6] = w[5];
2606               
2607        hDist = -1.0*sqrt(fabs(endRad*endRad-rad*rad));         //by definition for this model
2608       
2609        contr = sldc-slds;
2610       
2611        Pi = 4.0*atan(1.0);
2612        va = 0.0;
2613        vb = Pi/2.0;            //orintational average, outer integral
2614        vaj = -1.0*hDist/endRad;
2615        vbj = 1.0;              //endpoints of inner integral
2616
2617        summ = 0.0;                     //initialize intergral
2618
2619        for(i=0;i<nordi;i++) {
2620                //setup inner integral over the ellipsoidal cross-section
2621                summj=0.0;
2622                zi = ( Gauss76Z[i]*(vb-va) + va + vb )/2.0;             //the "theta" dummy
2623               
2624                for(j=0;j<nordj;j++) {
2625                        //20 gauss points for the inner integral
2626                        zij = ( Gauss76Z[j]*(vbj-vaj) + vaj + vbj )/2.0;                //the "t" dummy
2627                        yyy = Gauss76Wt[j] * ConvLens_kernel(CLens_tmp,x,zij,zi);
2628                        summj += yyy;
2629                }
2630                //now calculate the value of the inner integral
2631                inner = (vbj-vaj)/2.0*summj;
2632                inner *= 4.0*Pi*endRad*endRad*endRad;
2633               
2634                //now calculate outer integrand
2635                arg1 = x*len/2.0*cos(zi);
2636                arg2 = x*rad*sin(zi);
2637                yyy = inner;
2638               
2639                if(arg2 == 0) {
2640                        be = 0.5;
2641                } else {
2642                        be = NR_BessJ1(arg2)/arg2;
2643                }
2644               
2645                if(arg1 == 0.0) {               //limiting value of sinc(0) is 1; sinc is not defined in math.h
2646                        yyy += Pi*rad*rad*len*2.0*be;
2647                } else {
2648                        yyy += Pi*rad*rad*len*sin(arg1)/arg1*2.0*be;
2649                }
2650                yyy *= yyy;
2651                yyy *= sin(zi);         // = |A(q)|^2*sin(theta)
2652                yyy *= Gauss76Wt[i];
2653                summ += yyy;
2654        }               //final scaling is done at the end of the function, after the NT_FP64 case
2655       
2656        answer = (vb-va)/2.0*summ;
2657
2658        hh = fabs(hDist);               //need positive value for spherical cap volume
2659        answer /= 2.0*(1.0/3.0*Pi*(endRad-hh)*(endRad-hh)*(2.0*endRad+hh));             //divide by volume
2660        answer *= 1.0e8;                //convert to cm^-1
2661        answer *= contr*contr;
2662        answer *= scale;
2663        answer += bkg;
2664               
2665        return answer;
2666}
2667
2668/*      Capped Cylinder  : special case where L is nonzero and hDist < 0
2669
2670 -- uses the same Kernel as the Convex Lens
2671 
2672Uses 76 pt Gaussian quadrature for both integrals
2673*/
2674double
2675CappedCylinder(double w[], double x)
2676{
2677        int i,j;
2678        double Pi;
2679        double scale,contr,bkg,sldc,slds;
2680        double len,rad,hDist,endRad;
2681        int nordi=76;                   //order of integration
2682        int nordj=76;
2683        double va,vb;           //upper and lower integration limits
2684        double summ,zi,yyy,answer;                      //running tally of integration
2685        double summj,vaj,vbj,zij;                       //for the inner integration
2686        double arg1,arg2,inner,hh,be;
2687       
2688       
2689        scale = w[0];
2690        rad = w[1];
2691        len = w[2];
2692        endRad = w[3];
2693        sldc = w[4];
2694        slds = w[5];
2695        bkg = w[6];
2696               
2697        hDist = -1.0*sqrt(fabs(endRad*endRad-rad*rad));         //by definition for this model
2698       
2699        contr = sldc-slds;
2700       
2701        Pi = 4.0*atan(1.0);
2702        va = 0.0;
2703        vb = Pi/2.0;            //orintational average, outer integral
2704        vaj = -1.0*hDist/endRad;
2705        vbj = 1.0;              //endpoints of inner integral
2706
2707        summ = 0.0;                     //initialize intergral
2708
2709        for(i=0;i<nordi;i++) {
2710                //setup inner integral over the ellipsoidal cross-section
2711                summj=0.0;
2712                zi = ( Gauss76Z[i]*(vb-va) + va + vb )/2.0;             //the "theta" dummy
2713               
2714                for(j=0;j<nordj;j++) {
2715                        //20 gauss points for the inner integral
2716                        zij = ( Gauss76Z[j]*(vbj-vaj) + vaj + vbj )/2.0;                //the "t" dummy
2717                        yyy = Gauss76Wt[j] * ConvLens_kernel(w,x,zij,zi);               //uses the same kernel as ConvexLens, except here L != 0
2718                        summj += yyy;
2719                }
2720                //now calculate the value of the inner integral
2721                inner = (vbj-vaj)/2.0*summj;
2722                inner *= 4.0*Pi*endRad*endRad*endRad;
2723               
2724                //now calculate outer integrand
2725                arg1 = x*len/2.0*cos(zi);
2726                arg2 = x*rad*sin(zi);
2727                yyy = inner;
2728               
2729                if(arg2 == 0) {
2730                        be = 0.5;
2731                } else {
2732                        be = NR_BessJ1(arg2)/arg2;
2733                }
2734               
2735                if(arg1 == 0.0) {               //limiting value of sinc(0) is 1; sinc is not defined in math.h
2736                        yyy += Pi*rad*rad*len*2.0*be;
2737                } else {
2738                        yyy += Pi*rad*rad*len*sin(arg1)/arg1*2.0*be;
2739                }
2740               
2741               
2742               
2743                yyy *= yyy;
2744                yyy *= sin(zi);         // = |A(q)|^2*sin(theta)
2745                yyy *= Gauss76Wt[i];
2746                summ += yyy;
2747        }               //final scaling is done at the end of the function, after the NT_FP64 case
2748       
2749        answer = (vb-va)/2.0*summ;
2750
2751        hh = fabs(hDist);               //need positive value for spherical cap volume
2752        answer /= Pi*rad*rad*len + 2.0*(1.0/3.0*Pi*(endRad-hh)*(endRad-hh)*(2.0*endRad+hh));            //divide by volume
2753        answer *= 1.0e8;                //convert to cm^-1
2754        answer *= contr*contr;
2755        answer *= scale;
2756        answer += bkg;
2757               
2758        return answer;
2759}
2760
2761
2762
2763// inner integral of the ConvexLens model, special case where L ~ 0 and hDist < 0
2764//
2765double
2766ConvLens_kernel(double w[], double x, double tt, double theta) {
2767
2768        double val,arg1,arg2;
2769        double scale,bkg,sldc,slds;
2770        double len,rad,hDist,endRad,be;
2771        scale = w[0];
2772        rad = w[1];
2773        len = w[2];
2774        endRad = w[3];
2775        sldc = w[4];
2776        slds = w[5];
2777        bkg = w[6];
2778       
2779        hDist = -1.0*sqrt(fabs(endRad*endRad-rad*rad));
2780               
2781        arg1 = x*cos(theta)*(endRad*tt+hDist+len/2.0);
2782        arg2 = x*endRad*sin(theta)*sqrt(1.0-tt*tt);
2783       
2784        if(arg2 == 0) {
2785                be = 0.5;
2786        } else {
2787                be = NR_BessJ1(arg2)/arg2;
2788        }
2789       
2790        val = cos(arg1)*(1.0-tt*tt)*be;
2791       
2792        return(val);
2793}
2794
2795
2796/*      Dumbbell  : special case where L ~ 0 and hDist > 0
2797
2798Uses 76 pt Gaussian quadrature for both integrals
2799*/
2800double
2801Dumbbell(double w[], double x)
2802{
2803        int i,j;
2804        double Pi;
2805        double scale,contr,bkg,sldc,slds;
2806        double len,rad,hDist,endRad;
2807        int nordi=76;                   //order of integration
2808        int nordj=76;
2809        double va,vb;           //upper and lower integration limits
2810        double summ,zi,yyy,answer;                      //running tally of integration
2811        double summj,vaj,vbj,zij;                       //for the inner integration
2812        double Dumb_tmp[7],arg1,arg2,inner,be;
2813       
2814       
2815        scale = w[0];
2816        rad = w[1];
2817//      len = w[2]
2818        endRad = w[2];
2819        sldc = w[3];
2820        slds = w[4];
2821        bkg = w[5];
2822       
2823        len = 0.01;
2824       
2825        Dumb_tmp[0] = w[0];
2826        Dumb_tmp[1] = w[1];
2827        Dumb_tmp[2] = len;              //length is some small number, essentially zero
2828        Dumb_tmp[3] = w[2];
2829        Dumb_tmp[4] = w[3];
2830        Dumb_tmp[5] = w[4];
2831        Dumb_tmp[6] = w[5];
2832                       
2833        hDist = sqrt(fabs(endRad*endRad-rad*rad));              //by definition for this model
2834       
2835        contr = sldc-slds;
2836       
2837        Pi = 4.0*atan(1.0);
2838        va = 0.0;
2839        vb = Pi/2.0;            //orintational average, outer integral
2840        vaj = -1.0*hDist/endRad;
2841        vbj = 1.0;              //endpoints of inner integral
2842
2843        summ = 0.0;                     //initialize intergral
2844
2845        for(i=0;i<nordi;i++) {
2846                //setup inner integral over the ellipsoidal cross-section
2847                summj=0.0;
2848                zi = ( Gauss76Z[i]*(vb-va) + va + vb )/2.0;             //the "theta" dummy
2849               
2850                for(j=0;j<nordj;j++) {
2851                        //20 gauss points for the inner integral
2852                        zij = ( Gauss76Z[j]*(vbj-vaj) + vaj + vbj )/2.0;                //the "t" dummy
2853                        yyy = Gauss76Wt[j] * Dumb_kernel(Dumb_tmp,x,zij,zi);
2854                        summj += yyy;
2855                }
2856                //now calculate the value of the inner integral
2857                inner = (vbj-vaj)/2.0*summj;
2858                inner *= 4.0*Pi*endRad*endRad*endRad;
2859               
2860                //now calculate outer integrand
2861                arg1 = x*len/2.0*cos(zi);
2862                arg2 = x*rad*sin(zi);
2863                yyy = inner;
2864               
2865                if(arg2 == 0) {
2866                        be = 0.5;
2867                } else {
2868                        be = NR_BessJ1(arg2)/arg2;
2869                }
2870               
2871                if(arg1 == 0.0) {               //limiting value of sinc(0) is 1; sinc is not defined in math.h
2872                        yyy += Pi*rad*rad*len*2.0*be;
2873                } else {
2874                        yyy += Pi*rad*rad*len*sin(arg1)/arg1*2.0*be;
2875                }
2876                yyy *= yyy;
2877                yyy *= sin(zi);         // = |A(q)|^2*sin(theta)
2878                yyy *= Gauss76Wt[i];
2879                summ += yyy;
2880        }               //final scaling is done at the end of the function, after the NT_FP64 case
2881       
2882        answer = (vb-va)/2.0*summ;
2883
2884        answer /= 2.0*Pi*(2.0*endRad*endRad*endRad/3.0+endRad*endRad*hDist-hDist*hDist*hDist/3.0);              //divide by volume
2885        answer *= 1.0e8;                //convert to cm^-1
2886        answer *= contr*contr;
2887        answer *= scale;
2888        answer += bkg;
2889               
2890        return answer;
2891}
2892
2893
2894/*      Barbell  : "normal" case where L is nonzero 0 and hDist > 0
2895
2896-- uses the same kernel as the Dumbbell case
2897
2898Uses 76 pt Gaussian quadrature for both integrals
2899*/
2900double
2901Barbell(double w[], double x)
2902{
2903        int i,j;
2904        double Pi;
2905        double scale,contr,bkg,sldc,slds;
2906        double len,rad,hDist,endRad;
2907        int nordi=76;                   //order of integration
2908        int nordj=76;
2909        double va,vb;           //upper and lower integration limits
2910        double summ,zi,yyy,answer;                      //running tally of integration
2911        double summj,vaj,vbj,zij;                       //for the inner integration
2912        double arg1,arg2,inner,be;
2913       
2914       
2915        scale = w[0];
2916        rad = w[1];
2917        len = w[2];
2918        endRad = w[3];
2919        sldc = w[4];
2920        slds = w[5];
2921        bkg = w[6];
2922                       
2923        hDist = sqrt(fabs(endRad*endRad-rad*rad));              //by definition for this model
2924       
2925        contr = sldc-slds;
2926       
2927        Pi = 4.0*atan(1.0);
2928        va = 0.0;
2929        vb = Pi/2.0;            //orintational average, outer integral
2930        vaj = -1.0*hDist/endRad;
2931        vbj = 1.0;              //endpoints of inner integral
2932
2933        summ = 0.0;                     //initialize intergral
2934
2935        for(i=0;i<nordi;i++) {
2936                //setup inner integral over the ellipsoidal cross-section
2937                summj=0.0;
2938                zi = ( Gauss76Z[i]*(vb-va) + va + vb )/2.0;             //the "theta" dummy
2939               
2940                for(j=0;j<nordj;j++) {
2941                        //20 gauss points for the inner integral
2942                        zij = ( Gauss76Z[j]*(vbj-vaj) + vaj + vbj )/2.0;                //the "t" dummy
2943                        yyy = Gauss76Wt[j] * Dumb_kernel(w,x,zij,zi);           //uses the same Kernel as the Dumbbell, here L>0
2944                        summj += yyy;
2945                }
2946                //now calculate the value of the inner integral
2947                inner = (vbj-vaj)/2.0*summj;
2948                inner *= 4.0*Pi*endRad*endRad*endRad;
2949               
2950                //now calculate outer integrand
2951                arg1 = x*len/2.0*cos(zi);
2952                arg2 = x*rad*sin(zi);
2953                yyy = inner;
2954               
2955                if(arg2 == 0) {
2956                        be = 0.5;
2957                } else {
2958                        be = NR_BessJ1(arg2)/arg2;
2959                }
2960               
2961                if(arg1 == 0.0) {               //limiting value of sinc(0) is 1; sinc is not defined in math.h
2962                        yyy += Pi*rad*rad*len*2.0*be;
2963                } else {
2964                        yyy += Pi*rad*rad*len*sin(arg1)/arg1*2.0*be;
2965                }
2966                yyy *= yyy;
2967                yyy *= sin(zi);         // = |A(q)|^2*sin(theta)
2968                yyy *= Gauss76Wt[i];
2969                summ += yyy;
2970        }               //final scaling is done at the end of the function, after the NT_FP64 case
2971       
2972        answer = (vb-va)/2.0*summ;
2973
2974        answer /= Pi*rad*rad*len + 2.0*Pi*(2.0*endRad*endRad*endRad/3.0+endRad*endRad*hDist-hDist*hDist*hDist/3.0);             //divide by volume
2975        answer *= 1.0e8;                //convert to cm^-1
2976        answer *= contr*contr;
2977        answer *= scale;
2978        answer += bkg;
2979               
2980        return answer;
2981}
2982
2983
2984
2985// inner integral of the Dumbbell model, special case where L ~ 0 and hDist > 0
2986//
2987// inner integral of the Barbell model if L is nonzero
2988//
2989double
2990Dumb_kernel(double w[], double x, double tt, double theta) {
2991
2992        double val,arg1,arg2;
2993        double scale,bkg,sldc,slds;
2994        double len,rad,hDist,endRad,be;
2995        scale = w[0];
2996        rad = w[1];
2997        len = w[2];
2998        endRad = w[3];
2999        sldc = w[4];
3000        slds = w[5];
3001        bkg = w[6];
3002       
3003        hDist = sqrt(fabs(endRad*endRad-rad*rad));
3004               
3005        arg1 = x*cos(theta)*(endRad*tt+hDist+len/2.0);
3006        arg2 = x*endRad*sin(theta)*sqrt(1.0-tt*tt);
3007       
3008        if(arg2 == 0) {
3009                be = 0.5;
3010        } else {
3011                be = NR_BessJ1(arg2)/arg2;
3012        }
3013        val = cos(arg1)*(1.0-tt*tt)*be;
3014       
3015        return(val);
3016}
3017
3018double PolyCoreBicelle(double dp[], double q)
3019{
3020        int i;
3021        int nord = 20;
3022        double scale, length, sigma, bkg, radius, radthick, facthick;
3023        double rhoc, rhoh, rhor, rhosolv;
3024        double answer, Vpoly;
3025        double Pi,lolim,uplim,summ,yyy,rad,AR,Rsqr,Rsqrsumm,Rsqryyy;
3026       
3027        scale = dp[0];
3028        radius = dp[1];
3029        sigma = dp[2];                          //sigma is the standard mean deviation
3030        length = dp[3];
3031        radthick = dp[4];
3032        facthick= dp[5];
3033        rhoc = dp[6];
3034        rhoh = dp[7];
3035        rhor=dp[8];
3036        rhosolv = dp[9];
3037        bkg = dp[10];
3038       
3039        Pi = 4.0*atan(1.0);
3040       
3041        lolim = exp(log(radius)-(4.*sigma));
3042        if (lolim<0.0) {
3043                lolim=0.0;              //to avoid numerical error when  va<0 (-ve r value)
3044        }
3045        uplim = exp(log(radius)+(4.*sigma));
3046       
3047        summ = 0.0;
3048        Rsqrsumm = 0.0;
3049       
3050        for(i=0;i<nord;i++) {
3051                rad = ( Gauss20Z[i]*(uplim-lolim) + uplim + lolim )/2.0;
3052                AR=(1.0/(rad*sigma*sqrt(2.0*Pi)))*exp(-(0.5*((log(radius/rad))/sigma)*((log(radius/rad))/sigma)));
3053                yyy = AR* Gauss20Wt[i] * BicelleIntegration(q,rad,radthick,facthick,rhoc,rhoh,rhor,rhosolv,length);
3054                Rsqryyy= Gauss20Wt[i] * AR * (rad+radthick)*(rad+radthick);             //SRK normalize to total dimensions
3055                summ += yyy;
3056                Rsqrsumm += Rsqryyy;
3057        }
3058       
3059        answer = (uplim-lolim)/2.0*summ;
3060        Rsqr = (uplim-lolim)/2.0*Rsqrsumm;
3061        //normalize by average cylinder volume
3062        Vpoly = Pi*Rsqr*(length+2*facthick);
3063        answer /= Vpoly;
3064        //convert to [cm-1]
3065        answer *= 1.0e8;
3066        //Scale
3067        answer *= scale;
3068        // add in the background
3069        answer += bkg;
3070               
3071        return answer;
3072       
3073}
3074
3075double
3076BicelleIntegration(double qq, double rad, double radthick, double facthick, double rhoc, double rhoh, double rhor, double rhosolv, double length){
3077
3078        double answer,halfheight,Pi;
3079        double lolim,uplim,summ,yyy,zi;
3080        int nord,i;
3081       
3082        // set up the integration end points
3083        Pi = 4.0*atan(1.0);
3084        nord = 76;
3085        lolim = 0.0;
3086        uplim = Pi/2;
3087        halfheight = length/2.0;
3088       
3089        summ = 0.0;                             // initialize integral
3090        i=0;
3091        for(i=0;i<nord;i++) {
3092                zi = ( Gauss76Z[i]*(uplim-lolim) + uplim + lolim )/2.0;
3093                yyy = Gauss76Wt[i] * BicelleKernel(qq, rad, radthick, facthick, rhoc, rhoh, rhor,rhosolv, halfheight, zi);
3094                summ += yyy;
3095        }
3096       
3097        // calculate value of integral to return
3098        answer = (uplim-lolim)/2.0*summ;
3099        return(answer); 
3100}
3101
3102double
3103BicelleKernel(double qq, double rad, double radthick, double facthick, double rhoc, double rhoh, double rhor, double rhosolv, double length, double dum)
3104{
3105        double dr1,dr2,dr3;
3106        double besarg1,besarg2;
3107        double vol1,vol2,vol3;
3108        double sinarg1,sinarg2;
3109        double t1,t2,t3;
3110        double retval,si1,si2,be1,be2;
3111       
3112        double Pi = 4.0*atan(1.0);
3113       
3114        dr1 = rhoc-rhoh;
3115        dr2 = rhor-rhosolv;
3116        dr3=  rhoh-rhor;
3117        vol1 = Pi*rad*rad*(2.0*length);
3118        vol2 = Pi*(rad+radthick)*(rad+radthick)*(2.0*length+2.0*facthick);
3119        vol3= Pi*(rad)*(rad)*(2.0*length+2.0*facthick);
3120        besarg1 = qq*rad*sin(dum);
3121        besarg2 = qq*(rad+radthick)*sin(dum);
3122        sinarg1 = qq*length*cos(dum);
3123        sinarg2 = qq*(length+facthick)*cos(dum);
3124       
3125        if(besarg1 == 0) {
3126                be1 = 0.5;
3127        } else {
3128                be1 = NR_BessJ1(besarg1)/besarg1;
3129        }
3130        if(besarg2 == 0) {
3131                be2 = 0.5;
3132        } else {
3133                be2 = NR_BessJ1(besarg2)/besarg2;
3134        }       
3135        if(sinarg1 == 0) {
3136                si1 = 1.0;
3137        } else {
3138                si1 = sin(sinarg1)/sinarg1;
3139        }
3140        if(sinarg2 == 0) {
3141                si2 = 1.0;
3142        } else {
3143                si2 = sin(sinarg2)/sinarg2;
3144        }
3145        t1 = 2.0*vol1*dr1*si1*be1;
3146        t2 = 2.0*vol2*dr2*si2*be2;
3147        t3 = 2.0*vol3*dr3*si2*be1;
3148       
3149        retval = ((t1+t2+t3)*(t1+t2+t3))*sin(dum);
3150        return(retval);
3151       
3152}
3153
3154
3155double
3156CSPPKernel(double dp[], double mu, double uu)
3157{       
3158        double aa,bb,cc, ta,tb,tc; 
3159        double Vin,Vot,V1,V2;
3160        double rhoA,rhoB,rhoC, rhoP, rhosolv;
3161        double dr0, drA,drB, drC;
3162        double arg1,arg2,arg3,arg4,t1,t2, t3, t4;
3163        double Pi,retVal;
3164
3165        aa = dp[1];
3166        bb = dp[2];
3167        cc = dp[3];
3168        ta = dp[4];
3169        tb = dp[5];
3170        tc = dp[6];
3171        rhoA=dp[7];
3172        rhoB=dp[8];
3173        rhoC=dp[9];
3174        rhoP=dp[10];
3175        rhosolv=dp[11];
3176        dr0=rhoP-rhosolv;
3177        drA=rhoA-rhosolv;
3178        drB=rhoB-rhosolv;
3179        drC=rhoC-rhosolv; 
3180        Vin=(aa*bb*cc);
3181        Vot=(aa*bb*cc+2.0*ta*bb*cc+2.0*aa*tb*cc+2.0*aa*bb*tc);
3182        V1=(2.0*ta*bb*cc);   //  incorrect V1 (aa*bb*cc+2*ta*bb*cc)
3183        V2=(2.0*aa*tb*cc);  // incorrect V2(aa*bb*cc+2*aa*tb*cc)
3184        aa = aa/bb;
3185        ta=(aa+2.0*ta)/bb;
3186        tb=(aa+2.0*tb)/bb;
3187       
3188        Pi = 4.0*atan(1.0);
3189       
3190        arg1 = (mu*aa/2.0)*sin(Pi*uu/2.0);
3191        arg2 = (mu/2.0)*cos(Pi*uu/2.0);
3192        arg3=  (mu*ta/2.0)*sin(Pi*uu/2.0);
3193        arg4=  (mu*tb/2.0)*cos(Pi*uu/2.0);
3194                         
3195        if(arg1==0.0){
3196                t1 = 1.0;
3197        } else {
3198                t1 = (sin(arg1)/arg1);                //defn for CSPP model sin(arg1)/arg1    test:  (sin(arg1)/arg1)*(sin(arg1)/arg1)   
3199        }
3200        if(arg2==0.0){
3201                t2 = 1.0;
3202        } else {
3203                t2 = (sin(arg2)/arg2);           //defn for CSPP model sin(arg2)/arg2   test: (sin(arg2)/arg2)*(sin(arg2)/arg2)   
3204        }       
3205        if(arg3==0.0){
3206                t3 = 1.0;
3207        } else {
3208                t3 = sin(arg3)/arg3;
3209        }
3210        if(arg4==0.0){
3211                t4 = 1.0;
3212        } else {
3213                t4 = sin(arg4)/arg4;
3214        }
3215        retVal =( dr0*t1*t2*Vin + drA*(t3-t1)*t2*V1+ drB*t1*(t4-t2)*V2 )*( dr0*t1*t2*Vin + drA*(t3-t1)*t2*V1+ drB*t1*(t4-t2)*V2 );   //  correct FF : square of sum of phase factors
3216        return(retVal); 
3217
3218}
3219
3220/*      CSParallelepiped  :  calculates the form factor of a Parallelepiped with a core-shell structure
3221 -- different SLDs can be used for the face and rim
3222
3223Uses 76 pt Gaussian quadrature for both integrals
3224*/
3225double
3226CSParallelepiped(double dp[], double q)
3227{
3228        int i,j;
3229        double scale,aa,bb,cc,ta,tb,tc,rhoA,rhoB,rhoC,rhoP,rhosolv,bkg;         //local variables of coefficient wave
3230        int nordi=76;                   //order of integration
3231        int nordj=76;
3232        double va,vb;           //upper and lower integration limits
3233        double summ,yyy,answer;                 //running tally of integration
3234        double summj,vaj,vbj;                   //for the inner integration
3235        double mu,mudum,arg,sigma,uu,vol;
3236       
3237       
3238        //      Pi = 4.0*atan(1.0);
3239        va = 0.0;
3240        vb = 1.0;               //orintational average, outer integral
3241        vaj = 0.0;
3242        vbj = 1.0;              //endpoints of inner integral
3243       
3244        summ = 0.0;                     //initialize intergral
3245       
3246        scale = dp[0];
3247        aa = dp[1];
3248        bb = dp[2];
3249        cc = dp[3];
3250        ta  = dp[4];
3251        tb  = dp[5];
3252        tc  = dp[6];   // is 0 at the moment 
3253        rhoA=dp[7];   //rim A SLD
3254        rhoB=dp[8];   //rim B SLD
3255        rhoC=dp[9];    //rim C SLD
3256        rhoP = dp[10];   //Parallelpiped core SLD
3257        rhosolv=dp[11];  // Solvent SLD
3258        bkg = dp[12];
3259       
3260        mu = q*bb;
3261        vol = aa*bb*cc+2.0*ta*bb*cc+2.0*aa*tb*cc+2.0*aa*bb*tc;          //calculate volume before rescaling
3262       
3263        // do the rescaling here, not in the kernel
3264        // normalize all WRT bb
3265        aa = aa/bb;
3266        cc = cc/bb;
3267       
3268        for(i=0;i<nordi;i++) {
3269                //setup inner integral over the ellipsoidal cross-section
3270                summj=0.0;
3271                sigma = ( Gauss76Z[i]*(vb-va) + va + vb )/2.0;          //the outer dummy
3272               
3273                for(j=0;j<nordj;j++) {
3274                        //76 gauss points for the inner integral
3275                        uu = ( Gauss76Z[j]*(vbj-vaj) + vaj + vbj )/2.0;         //the inner dummy
3276                        mudum = mu*sqrt(1.0-sigma*sigma);
3277                        yyy = Gauss76Wt[j] * CSPPKernel(dp,mudum,uu);
3278                        summj += yyy;
3279                }
3280                //now calculate the value of the inner integral
3281                answer = (vbj-vaj)/2.0*summj;
3282               
3283                //finish the outer integral cc already scaled
3284                arg = mu*cc*sigma/2.0;
3285                if ( arg == 0.0 ) {
3286                        answer *= 1.0;
3287                } else {
3288                        answer *= sin(arg)*sin(arg)/arg/arg;
3289                }
3290               
3291                //now sum up the outer integral
3292                yyy = Gauss76Wt[i] * answer;
3293                summ += yyy;
3294        }               //final scaling is done at the end of the function, after the NT_FP64 case
3295       
3296        answer = (vb-va)/2.0*summ;
3297
3298        //normalize by volume
3299        answer /= vol;
3300        //convert to [cm-1]
3301        answer *= 1.0e8;
3302        //Scale
3303        answer *= scale;
3304        // add in the background
3305        answer += bkg;
3306       
3307        return answer;
3308}
3309
Note: See TracBrowser for help on using the repository browser.