Ticket #1243: six_shells_01.c

File six_shells_01.c, 5.0 KB (added by butler, 6 years ago)

c part of model used in project file

Line 
1double lognormal(double r, double median, double sigma);
2double 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);
3double 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);
4double 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);
5double 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
14double 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
25double 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
64double 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}
119double 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}