source: sasmodels/sasmodels/models/rectangular_prism.c @ ee60aa7

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

clean up effective radius functions; improve mono_gauss_coil accuracy; start moving VR into C

  • Property mode set to 100644
File size: 6.2 KB
Line 
1static double
2form_volume(double length_a, double b2a_ratio, double c2a_ratio)
3{
4    return length_a * (length_a*b2a_ratio) * (length_a*c2a_ratio);
5}
6
7static double
8effective_radius(int mode, double length_a, double b2a_ratio, double c2a_ratio)
9{
10    switch (mode) {
11    case 1: // equivalent sphere
12        return cbrt(0.75*cube(length_a)*b2a_ratio*c2a_ratio/M_PI);
13    case 2: // half length_a
14        return 0.5 * length_a;
15    case 3: // half length_b
16        return 0.5 * length_a*b2a_ratio;
17    case 4: // half length_c
18        return 0.5 * length_a*c2a_ratio;
19    case 5: // equivalent circular cross-section
20        return length_a*sqrt(b2a_ratio/M_PI);
21    case 6: // half ab diagonal
22        return 0.5*sqrt(square(length_a) * (1.0 + square(b2a_ratio)));
23    case 7: // half diagonal
24        return 0.5*sqrt(square(length_a) * (1.0 + square(b2a_ratio) + square(c2a_ratio)));
25    }
26}
27
28static double
29Iq(double q,
30    double sld,
31    double solvent_sld,
32    double length_a,
33    double b2a_ratio,
34    double c2a_ratio)
35{
36    const double length_b = length_a * b2a_ratio;
37    const double length_c = length_a * c2a_ratio;
38    const double a_half = 0.5 * length_a;
39    const double b_half = 0.5 * length_b;
40    const double c_half = 0.5 * length_c;
41
42   //Integration limits to use in Gaussian quadrature
43    const double v1a = 0.0;
44    const double v1b = M_PI_2;  //theta integration limits
45    const double v2a = 0.0;
46    const double v2b = M_PI_2;  //phi integration limits
47
48    double outer_sum = 0.0;
49    for(int i=0; i<GAUSS_N; i++) {
50        const double theta = 0.5 * ( GAUSS_Z[i]*(v1b-v1a) + v1a + v1b );
51        double sin_theta, cos_theta;
52        SINCOS(theta, sin_theta, cos_theta);
53
54        const double termC = sas_sinx_x(q * c_half * cos_theta);
55
56        double inner_sum = 0.0;
57        for(int j=0; j<GAUSS_N; j++) {
58            double phi = 0.5 * ( GAUSS_Z[j]*(v2b-v2a) + v2a + v2b );
59            double sin_phi, cos_phi;
60            SINCOS(phi, sin_phi, cos_phi);
61
62            // Amplitude AP from eqn. (12), rewritten to avoid round-off effects when arg=0
63            const double termA = sas_sinx_x(q * a_half * sin_theta * sin_phi);
64            const double termB = sas_sinx_x(q * b_half * sin_theta * cos_phi);
65            const double AP = termA * termB * termC;
66            inner_sum += GAUSS_W[j] * AP * AP;
67        }
68        inner_sum = 0.5 * (v2b-v2a) * inner_sum;
69        outer_sum += GAUSS_W[i] * inner_sum * sin_theta;
70    }
71
72    double answer = 0.5*(v1b-v1a)*outer_sum;
73
74    // Normalize by Pi (Eqn. 16).
75    // The term (ABC)^2 does not appear because it was introduced before on
76    // the definitions of termA, termB, termC.
77    // The factor 2 appears because the theta integral has been defined between
78    // 0 and pi/2, instead of 0 to pi.
79    answer /= M_PI_2; //Form factor P(q)
80
81    // Multiply by contrast^2 and volume^2
82    const double volume = length_a * length_b * length_c;
83    answer *= square((sld-solvent_sld)*volume);
84
85    // Convert from [1e-12 A-1] to [cm-1]
86    answer *= 1.0e-4;
87
88    return answer;
89}
90
91static void
92Fq(double q,
93    double *F1,
94    double *F2,
95    double sld,
96    double solvent_sld,
97    double length_a,
98    double b2a_ratio,
99    double c2a_ratio)
100{
101    const double length_b = length_a * b2a_ratio;
102    const double length_c = length_a * c2a_ratio;
103    const double a_half = 0.5 * length_a;
104    const double b_half = 0.5 * length_b;
105    const double c_half = 0.5 * length_c;
106
107   //Integration limits to use in Gaussian quadrature
108    const double v1a = 0.0;
109    const double v1b = M_PI_2;  //theta integration limits
110    const double v2a = 0.0;
111    const double v2b = M_PI_2;  //phi integration limits
112
113    double outer_sum_F1 = 0.0;
114    double outer_sum_F2 = 0.0;
115    for(int i=0; i<GAUSS_N; i++) {
116        const double theta = 0.5 * ( GAUSS_Z[i]*(v1b-v1a) + v1a + v1b );
117        double sin_theta, cos_theta;
118        SINCOS(theta, sin_theta, cos_theta);
119
120        const double termC = sas_sinx_x(q * c_half * cos_theta);
121
122        double inner_sum_F1 = 0.0;
123        double inner_sum_F2 = 0.0;
124        for(int j=0; j<GAUSS_N; j++) {
125            double phi = 0.5 * ( GAUSS_Z[j]*(v2b-v2a) + v2a + v2b );
126            double sin_phi, cos_phi;
127            SINCOS(phi, sin_phi, cos_phi);
128
129            // Amplitude AP from eqn. (12), rewritten to avoid round-off effects when arg=0
130            const double termA = sas_sinx_x(q * a_half * sin_theta * sin_phi);
131            const double termB = sas_sinx_x(q * b_half * sin_theta * cos_phi);
132            const double AP = termA * termB * termC;
133            inner_sum_F1 += GAUSS_W[j] * AP;
134            inner_sum_F2 += GAUSS_W[j] * AP * AP;
135        }
136        inner_sum_F1 = 0.5 * (v2b-v2a) * inner_sum_F1;
137        inner_sum_F2 = 0.5 * (v2b-v2a) * inner_sum_F2;
138        outer_sum_F1 += GAUSS_W[i] * inner_sum_F1 * sin_theta;
139        outer_sum_F2 += GAUSS_W[i] * inner_sum_F2 * sin_theta;
140    }
141
142    outer_sum_F1 *= 0.5*(v1b-v1a);
143    outer_sum_F2 *= 0.5*(v1b-v1a);
144
145    // Normalize by Pi (Eqn. 16).
146    // The term (ABC)^2 does not appear because it was introduced before on
147    // the definitions of termA, termB, termC.
148    // The factor 2 appears because the theta integral has been defined between
149    // 0 and pi/2, instead of 0 to pi.
150    outer_sum_F1 /= M_PI_2;
151    outer_sum_F2 /= M_PI_2;
152
153    // Multiply by contrast and volume
154    const double s = (sld-solvent_sld) * (length_a * length_b * length_c);
155
156    // Convert from [1e-12 A-1] to [cm-1]
157    *F1 = 1e-2 * s * outer_sum_F1;
158    *F2 = 1e-4 * s * s * outer_sum_F2;
159}
160
161
162static double
163Iqabc(double qa, double qb, double qc,
164    double sld,
165    double solvent_sld,
166    double length_a,
167    double b2a_ratio,
168    double c2a_ratio)
169{
170    const double length_b = length_a * b2a_ratio;
171    const double length_c = length_a * c2a_ratio;
172    const double a_half = 0.5 * length_a;
173    const double b_half = 0.5 * length_b;
174    const double c_half = 0.5 * length_c;
175
176    // Amplitude AP from eqn. (13)
177    const double termA = sas_sinx_x(qa * a_half);
178    const double termB = sas_sinx_x(qb * b_half);
179    const double termC = sas_sinx_x(qc * c_half);
180    const double AP = termA * termB * termC;
181
182    // Multiply by contrast and volume
183    const double s = (sld-solvent_sld) * (length_a * length_b * length_c);
184
185    // Convert from [1e-12 A-1] to [cm-1]
186    return 1.0e-4 * square(s * AP);
187}
Note: See TracBrowser for help on using the repository browser.