source: sasmodels/sasmodels/models/elliptical_cylinder.c @ a94046f

core_shell_microgelsmagnetic_modelticket-1257-vesicle-productticket_1156ticket_1265_superballticket_822_more_unit_tests
Last change on this file since a94046f was a94046f, checked in by richardh, 6 years ago

some corrections to R_eff options

  • Property mode set to 100644
File size: 4.8 KB
Line 
1static double
2form_volume(double radius_minor, double r_ratio, double length)
3{
4    return M_PI * radius_minor * radius_minor * r_ratio * length;
5}
6
7static double
8radius_from_volume(double radius_minor, double r_ratio, double length)
9{
10    const double volume_ellcyl = form_volume(radius_minor,r_ratio,length);
11    return cbrt(0.75*volume_ellcyl/M_PI);
12}
13
14static double
15radius_from_min_dimension(double radius_minor, double r_ratio, double hlength)
16{
17    const double rad_min = (r_ratio > 1.0 ? radius_minor : r_ratio*radius_minor);
18    return (rad_min < length ? rad_min : hlength);
19}
20
21static double
22radius_from_max_dimension(double radius_minor, double r_ratio, double hlength)
23{
24    const double rad_max = (r_ratio < 1.0 ? radius_minor : r_ratio*radius_minor);
25    return (rad_max > length ? rad_max : hlength);
26}
27
28static double
29radius_from_diagonal(double radius_minor, double r_ratio, double length)
30{
31    const double radius_max = (r_ratio > 1.0 ? radius_minor*r_ratio : radius_minor);
32    return sqrt(radius_max*radius_max + 0.25*length*length);
33}
34
35static double
36effective_radius(int mode, double radius_minor, double r_ratio, double length)
37//effective_radius_type = ["equivalent sphere","average radius","min radius","max radius",
38//                         "equivalent circular cross-section","half length","half min dimension","half max dimension","half diagonal"]
39{
40    if (mode == 1) {
41        return radius_from_volume(radius_minor, r_ratio, length);
42    } else if (mode == 2) {
43        return 0.5*radius_minor*(1.0 + r_ratio);
44    } else if (mode == 3) {
45        return (r_ratio > 1.0 ? radius_minor : r_ratio*radius_minor);
46    } else if (mode == 4) {
47        return (r_ratio < 1.0 ? radius_minor : r_ratio*radius_minor);
48    } else if (mode == 5) {
49        return sqrt(radius_minor*radius_minor*r_ratio);
50    } else if (mode == 6) {
51        return 0.5*length;
52    } else if (mode == 7) {
53        return radius_from_min_dimension(radius_minor,r_ratio,0.5*length);
54    } else if (mode == 8) {
55        return radius_from_max_dimension(radius_minor,r_ratio,0.5*length);
56    } else {
57        return radius_from_diagonal(radius_minor,r_ratio,length);
58    }
59}
60
61static void
62Fq(double q, double *F1, double *F2, double radius_minor, double r_ratio, double length,
63   double sld, double solvent_sld)
64{
65    // orientational average limits
66    const double va = 0.0;
67    const double vb = 1.0;
68    // inner integral limits
69    const double vaj=0.0;
70    const double vbj=M_PI;
71
72    const double radius_major = r_ratio * radius_minor;
73    const double rA = 0.5*(square(radius_major) + square(radius_minor));
74    const double rB = 0.5*(square(radius_major) - square(radius_minor));
75
76    //initialize integral
77    double outer_sum_F1 = 0.0;
78    double outer_sum_F2 = 0.0;
79    for(int i=0;i<GAUSS_N;i++) {
80        //setup inner integral over the ellipsoidal cross-section
81        const double cos_val = ( GAUSS_Z[i]*(vb-va) + va + vb )/2.0;
82        const double sin_val = sqrt(1.0 - cos_val*cos_val);
83        //const double arg = radius_minor*sin_val;
84        double inner_sum_F1 = 0.0;
85        double inner_sum_F2 = 0.0;
86        for(int j=0;j<GAUSS_N;j++) {
87            const double theta = ( GAUSS_Z[j]*(vbj-vaj) + vaj + vbj )/2.0;
88            const double r = sin_val*sqrt(rA - rB*cos(theta));
89            const double be = sas_2J1x_x(q*r);
90            inner_sum_F1 += GAUSS_W[j] * be;
91            inner_sum_F2 += GAUSS_W[j] * be * be;
92        }
93        //now calculate the value of the inner integral
94        inner_sum_F1 *= 0.5*(vbj-vaj);
95        inner_sum_F2 *= 0.5*(vbj-vaj);
96
97        //now calculate outer integral
98        const double si = sas_sinx_x(q*0.5*length*cos_val);
99        outer_sum_F1 += GAUSS_W[i] * inner_sum_F1 * si;
100        outer_sum_F2 += GAUSS_W[i] * inner_sum_F2 * si * si;
101    }
102    // correct limits and divide integral by pi
103    outer_sum_F1 *= 0.5*(vb-va)/M_PI;
104    outer_sum_F2 *= 0.5*(vb-va)/M_PI;
105
106    // scale by contrast and volume, and convert to to 1/cm units
107    const double volume = form_volume(radius_minor, r_ratio, length);
108    const double contrast = sld - solvent_sld;
109    const double s = contrast*volume;
110    *F1 = 1.0e-2*s*outer_sum_F1;
111    *F2 = 1.0e-4*s*s*outer_sum_F2;
112}
113
114
115static double
116Iqabc(double qa, double qb, double qc,
117     double radius_minor, double r_ratio, double length,
118     double sld, double solvent_sld)
119{
120    // Compute:  r = sqrt((radius_major*cos_nu)^2 + (radius_minor*cos_mu)^2)
121    // Given:    radius_major = r_ratio * radius_minor
122    const double qr = radius_minor*sqrt(square(r_ratio*qb) + square(qa));
123    const double be = sas_2J1x_x(qr);
124    const double si = sas_sinx_x(qc*0.5*length);
125    const double fq = be * si;
126    const double contrast = sld - solvent_sld;
127    const double volume = form_volume(radius_minor, r_ratio, length);
128    return 1.0e-4 * square(contrast * volume * fq);
129}
Note: See TracBrowser for help on using the repository browser.