source: sasmodels/sasmodels/models/bcc_paracrystal.c @ 2a0b2b1

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

restructure all 2D models to work with (qa,qb,qc) = rotate(qx,qy) rather than working with angles directly in preparation for revised jitter algorithm

  • Property mode set to 100644
File size: 3.5 KB
Line 
1static double
2_sq_bcc(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 - qc + qb;
7    const double a2 = +qa + qc - qb;
8    const double a3 = -qa + qc + qb;
9
10    const double half_dnn = 0.5*dnn;
11    const double arg = 0.5*square(half_dnn*d_factor)*(a1*a1 + a2*a2 + a3*a3);
12
13#if 1
14    // Numerator: (1 - exp(a)^2)^3
15    //         => (-(exp(2a) - 1))^3
16    //         => -expm1(2a)^3
17    // Denominator: prod(1 - 2 cos(xk) exp(a) + exp(a)^2)
18    //         => exp(a)^2 - 2 cos(xk) exp(a) + 1
19    //         => (exp(a) - 2 cos(xk)) * exp(a) + 1
20    const double exp_arg = exp(-arg);
21    const double Sq = -cube(expm1(-2.0*arg))
22        / ( ((exp_arg - 2.0*cos(half_dnn*a1))*exp_arg + 1.0)
23          * ((exp_arg - 2.0*cos(half_dnn*a2))*exp_arg + 1.0)
24          * ((exp_arg - 2.0*cos(half_dnn*a3))*exp_arg + 1.0));
25#else
26    // Alternate form, which perhaps is more approachable
27    const double sinh_qd = sinh(arg);
28    const double cosh_qd = cosh(arg);
29    const double Sq = sinh_qd/(cosh_qd - cos(half_dnn*a1))
30                    * sinh_qd/(cosh_qd - cos(half_dnn*a2))
31                    * sinh_qd/(cosh_qd - cos(half_dnn*a3));
32#endif
33
34    return Sq;
35}
36
37
38// occupied volume fraction calculated from lattice symmetry and sphere radius
39static double
40_bcc_volume_fraction(double radius, double dnn)
41{
42    return 2.0*sphere_volume(sqrt(0.75)*radius/dnn);
43}
44
45static double
46form_volume(double radius)
47{
48    return sphere_volume(radius);
49}
50
51
52static double Iq(double q, double dnn,
53  double d_factor, double radius,
54  double sld, double solvent_sld)
55{
56    // translate a point in [-1,1] to a point in [0, 2 pi]
57    const double phi_m = M_PI;
58    const double phi_b = M_PI;
59    // translate a point in [-1,1] to a point in [0, pi]
60    const double theta_m = M_PI_2;
61    const double theta_b = M_PI_2;
62
63    double outer_sum = 0.0;
64    for(int i=0; i<150; i++) {
65        double inner_sum = 0.0;
66        const double theta = Gauss150Z[i]*theta_m + theta_b;
67        double sin_theta, cos_theta;
68        SINCOS(theta, sin_theta, cos_theta);
69        const double qc = q*cos_theta;
70        const double qab = q*sin_theta;
71        for(int j=0;j<150;j++) {
72            const double phi = Gauss150Z[j]*phi_m + phi_b;
73            double sin_phi, cos_phi;
74            SINCOS(phi, sin_phi, cos_phi);
75            const double qa = qab*cos_phi;
76            const double qb = qab*sin_phi;
77            const double fq = _sq_bcc(qa, qb, qc, dnn, d_factor);
78            inner_sum += Gauss150Wt[j] * fq;
79        }
80        inner_sum *= phi_m;  // sum(f(x)dx) = sum(f(x)) dx
81        outer_sum += Gauss150Wt[i] * inner_sum * sin_theta;
82    }
83    outer_sum *= theta_m;
84    const double Sq = outer_sum/(4.0*M_PI);
85    const double Pq = sphere_form(q, radius, sld, solvent_sld);
86
87    return _bcc_volume_fraction(radius, dnn) * Pq * Sq;
88}
89
90
91static double Iqxy(double qx, double qy,
92    double dnn, double d_factor, double radius,
93    double sld, double solvent_sld,
94    double theta, double phi, double psi)
95{
96    double q, zhat, yhat, xhat;
97    ORIENT_ASYMMETRIC(qx, qy, theta, phi, psi, q, xhat, yhat, zhat);
98    const double qa = q*xhat;
99    const double qb = q*yhat;
100    const double qc = q*zhat;
101
102    q = sqrt(qa*qa + qb*qb + qc*qc);
103    const double Pq = sphere_form(q, radius, sld, solvent_sld);
104    const double Sq = _sq_bcc(qa, qb, qc, dnn, d_factor);
105    return _bcc_volume_fraction(radius, dnn) * Pq * Sq;
106}
Note: See TracBrowser for help on using the repository browser.