source: sasmodels/sasmodels/models/bcc_paracrystal.c @ 642046e

ticket_1156
Last change on this file since 642046e was 642046e, checked in by Paul Kienzle <pkienzle@…>, 6 years ago

set particle volume fraction according to lattice spacing rather than nearest-neighbour distance

  • Property mode set to 100644
File size: 4.4 KB
RevLine 
[2a0b2b1]1static double
[6530963]2bcc_Zq(double qa, double qb, double qc, double lattice_spacing, double lattice_distortion)
[2a0b2b1]3{
[f728001]4    // Equations from Matsuoka 26-27-28, multiplied by |q|
5    const double a1 = (-qa + qb + qc)/2.0;
[7e0b281]6    const double a2 = (+qa - qb + qc)/2.0;
[f728001]7    const double a3 = (+qa + qb - qc)/2.0;
[2a0b2b1]8
[ea60e08]9#if 1
[f728001]10    // Matsuoka 29-30-31
11    //     Z_k numerator: 1 - exp(a)^2
12    //     Z_k denominator: 1 - 2 cos(d a_k) exp(a) + exp(2a)
13    // Rewriting numerator
14    //         => -(exp(2a) - 1)
15    //         => -expm1(2a)
16    // Rewriting denominator
17    //         => exp(a)^2 - 2 cos(d ak) exp(a) + 1)
18    //         => (exp(a) - 2 cos(d ak)) * exp(a) + 1
[6530963]19    const double arg = -0.5*square(lattice_spacing*lattice_distortion)*(a1*a1 + a2*a2 + a3*a3);
[7e0b281]20    const double exp_arg = exp(arg);
21    const double Zq = -cube(expm1(2.0*arg))
[6530963]22        / ( ((exp_arg - 2.0*cos(lattice_spacing*a1))*exp_arg + 1.0)
23          * ((exp_arg - 2.0*cos(lattice_spacing*a2))*exp_arg + 1.0)
24          * ((exp_arg - 2.0*cos(lattice_spacing*a3))*exp_arg + 1.0));
[f728001]25
26#elif 0
27    // ** Alternate form, which perhaps is more approachable
28    //     Z_k numerator   => -[(exp(2a) - 1) / 2.exp(a)] 2.exp(a)
29    //                     => -[sinh(a)] exp(a)
30    //     Z_k denominator => [(exp(2a) + 1) / 2.exp(a) - cos(d a_k)] 2.exp(a)
31    //                     => [cosh(a) - cos(d a_k)] 2.exp(a)
32    //     => Z_k = -sinh(a) / [cosh(a) - cos(d a_k)]
33    //            = sinh(-a) / [cosh(-a) - cos(d a_k)]
34    //
35    // One more step leads to the form in sasview 3.x for 2d models
36    //            = tanh(-a) / [1 - cos(d a_k)/cosh(-a)]
37    //
[6530963]38    const double arg = 0.5*square(lattice_spacing*lattice_distortion)*(a1*a1 + a2*a2 + a3*a3);
[2a0b2b1]39    const double sinh_qd = sinh(arg);
40    const double cosh_qd = cosh(arg);
[6530963]41    const double Zq = sinh_qd/(cosh_qd - cos(lattice_spacing*a1))
42                    * sinh_qd/(cosh_qd - cos(lattice_spacing*a2))
43                    * sinh_qd/(cosh_qd - cos(lattice_spacing*a3));
[f728001]44#else
[6530963]45    const double arg = 0.5*square(lattice_spacing*lattice_distortion)*(a1*a1 + a2*a2 + a3*a3);
[f728001]46    const double tanh_qd = tanh(arg);
47    const double cosh_qd = cosh(arg);
[6530963]48    const double Zq = tanh_qd/(1.0 - cos(lattice_spacing*a1)/cosh_qd)
49                    * tanh_qd/(1.0 - cos(lattice_spacing*a2)/cosh_qd)
50                    * tanh_qd/(1.0 - cos(lattice_spacing*a3)/cosh_qd);
[2a0b2b1]51#endif
[754c454]52
[7e0b281]53    return Zq;
[754c454]54}
55
56
[2a0b2b1]57// occupied volume fraction calculated from lattice symmetry and sphere radius
58static double
[6530963]59bcc_volume_fraction(double radius, double lattice_spacing)
[2a0b2b1]60{
[642046e]61    return 2.0*sphere_volume(radius/lattice_spacing);
[754c454]62}
63
[2a0b2b1]64static double
65form_volume(double radius)
66{
[ad90df9]67    return sphere_volume(radius);
[754c454]68}
69
70
[6530963]71static double Iq(double q, double lattice_spacing,
72    double lattice_distortion, double radius,
[becded3]73    double sld, double solvent_sld)
[2a0b2b1]74{
75    // translate a point in [-1,1] to a point in [0, 2 pi]
76    const double phi_m = M_PI;
77    const double phi_b = M_PI;
78    // translate a point in [-1,1] to a point in [0, pi]
79    const double theta_m = M_PI_2;
80    const double theta_b = M_PI_2;
81
82    double outer_sum = 0.0;
[74768cb]83    for(int i=0; i<GAUSS_N; i++) {
[2a0b2b1]84        double inner_sum = 0.0;
[74768cb]85        const double theta = GAUSS_Z[i]*theta_m + theta_b;
[2a0b2b1]86        double sin_theta, cos_theta;
87        SINCOS(theta, sin_theta, cos_theta);
88        const double qc = q*cos_theta;
89        const double qab = q*sin_theta;
[74768cb]90        for(int j=0;j<GAUSS_N;j++) {
91            const double phi = GAUSS_Z[j]*phi_m + phi_b;
[2a0b2b1]92            double sin_phi, cos_phi;
93            SINCOS(phi, sin_phi, cos_phi);
94            const double qa = qab*cos_phi;
95            const double qb = qab*sin_phi;
[6530963]96            const double form = bcc_Zq(qa, qb, qc, lattice_spacing, lattice_distortion);
[74768cb]97            inner_sum += GAUSS_W[j] * form;
[2a0b2b1]98        }
99        inner_sum *= phi_m;  // sum(f(x)dx) = sum(f(x)) dx
[74768cb]100        outer_sum += GAUSS_W[i] * inner_sum * sin_theta;
[2a0b2b1]101    }
102    outer_sum *= theta_m;
[7e0b281]103    const double Zq = outer_sum/(4.0*M_PI);
[2a0b2b1]104    const double Pq = sphere_form(q, radius, sld, solvent_sld);
[6530963]105    return bcc_volume_fraction(radius, lattice_spacing) * Pq * Zq;
[754c454]106}
107
108
[108e70e]109static double Iqabc(double qa, double qb, double qc,
[6530963]110    double lattice_spacing, double lattice_distortion, double radius,
[becded3]111    double sld, double solvent_sld)
[11ca2ab]112{
[becded3]113    const double q = sqrt(qa*qa + qb*qb + qc*qc);
[6530963]114    const double Zq = bcc_Zq(qa, qb, qc, lattice_spacing, lattice_distortion);
[2a0b2b1]115    const double Pq = sphere_form(q, radius, sld, solvent_sld);
[6530963]116    return bcc_volume_fraction(radius, lattice_spacing) * Pq * Zq;
[f728001]117}
Note: See TracBrowser for help on using the repository browser.