1 | double lognormal(double r, double median, double sigma); |
---|
2 | double Pq(double q, double t_c, double t_h, double t_p_in, double t_p_out, double rho_c, double rho_h, double rho_p_in, double rho_p_out, double rho_s_in, double rho_s_out, double R_current); |
---|
3 | double Iq(double q, double t_c, double t_h, double t_p_in, double t_p_out, double rho_c, double rho_h, double rho_p_in, double rho_p_out, double rho_s_in, double rho_s_out, double R_median, double sigma_R, int n_pts, int n_sigs, int polyparam, double constraint); |
---|
4 | double Iqxy(double qx, double qy, double t_c, double t_h, double t_p_in, double t_p_out, double rho_c, double rho_h, double rho_p_in, double rho_p_out, double rho_s_in, double rho_s_out, double R_median, double sigma_R, int n_pts, int n_sigs, int polyparam, double constraint); |
---|
5 | double form_volume(double R_median, double sigma_R); |
---|
6 | |
---|
7 | #define INVALID(v) (v.R_median<0, v.sigma_R<0, v.n_pts<0, v.n_pts>512, v.n_sigs<0, v.polyparam<1, v.polyparam>3, v.constraint<0) |
---|
8 | |
---|
9 | #define max(a,b) \ |
---|
10 | ({ __typeof__ (a) _a = (a); \ |
---|
11 | __typeof__ (b) _b = (b); \ |
---|
12 | _a > _b ? _a : _b; }) |
---|
13 | |
---|
14 | double lognormal(double r, double median, double sigma){ // this is only called for finite sigma, so no case sigma=0 covered |
---|
15 | const double sig = sigma/median; |
---|
16 | const double mu = log(median); |
---|
17 | if (r==0) { |
---|
18 | return 0; |
---|
19 | } |
---|
20 | else { |
---|
21 | return exp(-0.5*square((log(r)-mu)/sig))/(r*sig); |
---|
22 | } |
---|
23 | } |
---|
24 | |
---|
25 | double Pq(double q, double t_c, double t_h, double t_p_in, double t_p_out, double rho_c, double rho_h, double rho_p_in, double rho_p_out, double rho_s_in, double rho_s_out, double R_current){ |
---|
26 | double R[8]; |
---|
27 | double rho[8]; |
---|
28 | |
---|
29 | R[3] = R_current - t_c/2; |
---|
30 | R[4] = R_current + t_c/2; |
---|
31 | R[2] = R_current - t_c/2 - t_h; |
---|
32 | R[5] = R_current + t_c/2 + t_h; |
---|
33 | R[1] = R_current - t_c/2 - t_h - t_p_in; |
---|
34 | R[6] = R_current + t_c/2 + t_h + t_p_out; |
---|
35 | R[0] = 0.; |
---|
36 | |
---|
37 | R[7] = 0.; |
---|
38 | |
---|
39 | rho[0] = rho_s_in; |
---|
40 | rho[1] = rho_p_in; |
---|
41 | rho[2] = rho_h; |
---|
42 | rho[3] = rho_c; |
---|
43 | rho[4] = rho_h; |
---|
44 | rho[5] = rho_p_out; |
---|
45 | rho[6] = rho_s_out; |
---|
46 | |
---|
47 | rho[7] = 0; |
---|
48 | |
---|
49 | const double a0 = 2.8179403227e-6; // classical electron radius in nm |
---|
50 | |
---|
51 | double F = 0.; |
---|
52 | double V = 0.; |
---|
53 | for (int i=1;i<7;i++){ |
---|
54 | V = M_4PI_3*cube(R[i]); |
---|
55 | F += V*(rho[i]-rho[i-1])*sas_3j1x_x(q*R[i]); |
---|
56 | } |
---|
57 | if (V==0){ |
---|
58 | return 0; |
---|
59 | } else { |
---|
60 | return 1e6*a0*a0*F*F/V; // prefactor 1e6*a0^2 brings the intensity to mm^-1 if all radii are in nm and all densities are in e-/nm^3 |
---|
61 | } |
---|
62 | } |
---|
63 | |
---|
64 | double Iq(double q, double t_c, double t_h, double t_p_in, double t_p_out, double rho_c, double rho_h, double rho_p_in, double rho_p_out, double rho_s_in, double rho_s_out, double R_median, double sigma_R, const int n_pts, const int n_sigs, int polyparam, double constraint){ |
---|
65 | int i; |
---|
66 | double V; |
---|
67 | |
---|
68 | // size polydispersity distribution |
---|
69 | |
---|
70 | double r[512]; // this is an arbitrary number, one could use less |
---|
71 | double Pr[512]; // multiples of 2 probably give performance advantage |
---|
72 | |
---|
73 | const double Rmin = max(R_median-n_sigs*sigma_R, t_p_in+t_h+t_c/2); |
---|
74 | const double Rmax = R_median+n_sigs*sigma_R; |
---|
75 | const double dR = (Rmax - Rmin)/((double)n_pts-1); |
---|
76 | |
---|
77 | double Iq = 0; |
---|
78 | if (sigma_R>0) { |
---|
79 | double norm = 0.; |
---|
80 | if(polyparam==1){ // conventional normalization |
---|
81 | for (i=0;i<n_pts;i++){ |
---|
82 | r[i] = Rmin + i*dR; |
---|
83 | Pr[i] = lognormal(r[i],R_median,sigma_R); |
---|
84 | norm += Pr[i]*dR; |
---|
85 | } |
---|
86 | for (i=0;i<n_pts;i++){ |
---|
87 | Pr[i] /= norm; // ignores constraint |
---|
88 | } |
---|
89 | } else if (polyparam==2){ // area normalization |
---|
90 | for (i=0;i<n_pts;i++){ |
---|
91 | r[i] = Rmin + i*dR; |
---|
92 | Pr[i] = lognormal(r[i],R_median,sigma_R); |
---|
93 | norm += 4*M_PI*Pr[i]*(square(r[i]-t_c/2-t_h/2) + square(r[i]+t_c/2+t_h/2))*dR; |
---|
94 | } |
---|
95 | for (i=0;i<n_pts;i++){ |
---|
96 | V = M_4PI_3*cube(r[i]); |
---|
97 | Pr[i] *= V*constraint/norm; // returns V*P(R) |
---|
98 | } |
---|
99 | } else if (polyparam==3){ // volume normalization |
---|
100 | for (i=0;i<n_pts;i++){ |
---|
101 | r[i] = Rmin + i*dR; |
---|
102 | Pr[i] = lognormal(r[i],R_median,sigma_R); |
---|
103 | norm += M_4PI_3*Pr[i]*(cube(r[i]-t_c/2-t_h) - cube(r[i]-t_c/2-t_h-t_p_in) + cube(r[i]+t_c/2+t_h+t_p_out) - cube(r[i]+t_c/2+t_h))*dR; |
---|
104 | } |
---|
105 | for (i=0;i<n_pts;i++){ |
---|
106 | V = M_4PI_3*cube(r[i]); |
---|
107 | Pr[i] *= V*constraint/norm; // returns V*P(R) |
---|
108 | } |
---|
109 | } |
---|
110 | // model function evaluation |
---|
111 | for (i=0;i<n_pts;i++){ |
---|
112 | Iq += Pr[i]*Pq(q, t_c, t_h, t_p_in, t_p_out, rho_c, rho_h, rho_p_in, rho_p_out, rho_s_in, rho_s_out, r[i])*dR; |
---|
113 | } |
---|
114 | } else { |
---|
115 | Iq = Pq(q, t_c, t_h, t_p_in, t_p_out, rho_c, rho_h, rho_p_in, rho_p_out, rho_s_in, rho_s_out, R_median); // monodisperse case |
---|
116 | } |
---|
117 | return Iq; |
---|
118 | } |
---|
119 | double Iqxy(double qx, double qy, double t_c, double t_h, double t_p_in, double t_p_out, double rho_c, double rho_h, double rho_p_in, double rho_p_out, double rho_s_in, double rho_s_out, double R_median, double sigma_R, int n_pts, int n_sigs, int polyparam, double constraint){ |
---|
120 | const double q = sqrt(qx*qx + qy*qy); |
---|
121 | return Iq(q, t_c, t_h, t_p_in, t_p_out, rho_c, rho_h, rho_p_in, rho_p_out, rho_s_in, rho_s_out, R_median, sigma_R, n_pts, n_sigs, polyparam, constraint); |
---|
122 | } |
---|