source: sasmodels/explore/sc.c @ 7e0b281

core_shell_microgelsmagnetic_modelticket-1257-vesicle-productticket_1156ticket_1265_superballticket_822_more_unit_tests
Last change on this file since 7e0b281 was 7e0b281, checked in by Paul Kienzle <pkienzle@…>, 7 years ago

adjust paracrystal equations to better match terminology in Matsuoka paper

  • Property mode set to 100644
File size: 4.2 KB
Line 
1static double
2sc_Zq(double qa, double qb, double qc, double dnn, double d_factor)
3{
4    // Rewriting equations for efficiency, accuracy and readability, and so
5    // code is reusable between 1D and 2D models.
6    const double a1 = qa;
7    const double a2 = qb;
8    const double a3 = qc;
9
10    const double arg = -0.5*square(dnn*d_factor)*(a1*a1 + a2*a2 + a3*a3);
11
12    // Numerator: (1 - exp(a)^2)^3
13    //         => (-(exp(2a) - 1))^3
14    //         => -expm1(2a)^3
15    // Denominator: prod(1 - 2 cos(xk) exp(a) + exp(a)^2)
16    //         => exp(a)^2 - 2 cos(xk) exp(a) + 1
17    //         => (exp(a) - 2 cos(xk)) * exp(a) + 1
18    const double exp_arg = exp(arg);
19    const double Zq = -cube(expm1(2.0*arg))
20        / ( ((exp_arg - 2.0*cos(dnn*a1))*exp_arg + 1.0)
21          * ((exp_arg - 2.0*cos(dnn*a2))*exp_arg + 1.0)
22          * ((exp_arg - 2.0*cos(dnn*a3))*exp_arg + 1.0));
23
24    return Zq;
25}
26
27// occupied volume fraction calculated from lattice symmetry and sphere radius
28static double
29sc_volume_fraction(double radius, double dnn)
30{
31    return sphere_volume(radius/dnn);
32}
33
34static double
35form_volume(double radius)
36{
37    return sphere_volume(radius);
38}
39
40
41static double Iq(double q, double dnn,
42  double d_factor, double radius,
43  double sld, double solvent_sld,
44  double n, double sym)
45{
46double phi_m, phi_b, theta_m, theta_b;
47if (sym>0.) {
48    // translate a point in [-1,1] to a point in [0, 2 pi]
49    phi_m = M_PI_4;
50    phi_b = M_PI_4;
51    // translate a point in [-1,1] to a point in [0, pi]
52    theta_m = M_PI_4;
53    theta_b = M_PI_4;
54} else {
55    // translate a point in [-1,1] to a point in [0, 2 pi]
56    phi_m = M_PI;
57    phi_b = M_PI;
58    // translate a point in [-1,1] to a point in [0, pi]
59    theta_m = M_PI_2;
60    theta_b = M_PI_2;
61}
62
63#if 0
64    double outer_sum = 0.0;
65    for(int i=0; i<150; i++) {
66        double inner_sum = 0.0;
67        const double theta = Gauss150Z[i]*theta_m + theta_b;
68        double sin_theta, cos_theta;
69        SINCOS(theta, sin_theta, cos_theta);
70        const double qc = q*cos_theta;
71        const double qab = q*sin_theta;
72        for(int j=0;j<150;j++) {
73            const double phi = Gauss150Z[j]*phi_m + phi_b;
74            double sin_phi, cos_phi;
75            SINCOS(phi, sin_phi, cos_phi);
76            const double qa = qab*cos_phi;
77            const double qb = qab*sin_phi;
78            const double fq = _sq_sc(qa, qb, qc, dnn, d_factor);
79            inner_sum += Gauss150Wt[j] * fq;
80        }
81        inner_sum *= phi_m;  // sum(f(x)dx) = sum(f(x)) dx
82        outer_sum += Gauss150Wt[i] * inner_sum * sin_theta;
83    }
84    outer_sum *= theta_m;
85#else
86    double outer_sum = 0.0;
87    for(int i=0; i<(int)n; i++) {
88        double inner_sum = 0.0;
89        const double theta = (i*2./n-1.)*theta_m + theta_b;
90        double sin_theta, cos_theta;
91        SINCOS(theta, sin_theta, cos_theta);
92        const double qc = q*cos_theta;
93        const double qab = q*sin_theta;
94        for(int j=0;j<(int)n;j++) {
95            const double phi = (j*2./n-1.)*phi_m + phi_b;
96            double sin_phi, cos_phi;
97            SINCOS(phi, sin_phi, cos_phi);
98            const double qa = qab*cos_phi;
99            const double qb = qab*sin_phi;
100            const double form = sc_Zq(qa, qb, qc, dnn, d_factor);
101            inner_sum += form;
102        }
103        inner_sum *= phi_m;  // sum(f(x)dx) = sum(f(x)) dx
104        outer_sum += inner_sum * sin_theta;
105    }
106    outer_sum *= theta_m/(n*n);
107#endif
108double Zq;
109if (sym > 0.) {
110    Zq = outer_sum/M_PI_2;
111} else {
112    Zq = outer_sum/(4.0*M_PI);
113}
114
115    return Zq;
116    const double Pq = sphere_form(q, radius, sld, solvent_sld);
117    return sc_volume_fraction(radius, dnn) * Pq * Zq;
118}
119
120
121static double Iqxy(double qx, double qy,
122    double dnn, double d_factor, double radius,
123    double sld, double solvent_sld,
124    double n, double sym,
125    double theta, double phi, double psi)
126{
127    double q, zhat, yhat, xhat;
128    ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, xhat, yhat, zhat);
129    const double qa = q*xhat;
130    const double qb = q*yhat;
131    const double qc = q*zhat;
132
133    q = sqrt(qa*qa + qb*qb + qc*qc);
134    const double Pq = sphere_form(q, radius, sld, solvent_sld);
135    const double Zq = sc_Zq(qa, qb, qc, dnn, d_factor);
136    return sc_volume_fraction(radius, dnn) * Pq * Zq;
137}
Note: See TracBrowser for help on using the repository browser.