source: sasmodels/sasmodels/models/hollow_cylinder.c @ d507c3a

core_shell_microgelscostrafo411magnetic_modelrelease_v0.94release_v0.95ticket-1257-vesicle-productticket_1156ticket_1265_superballticket_822_more_unit_tests
Last change on this file since d507c3a was 0420af7, checked in by krzywon, 8 years ago

Modified hollow_cylinder to reject invalid inputs, added VR, ER and
tests. Si now has pre-calculated factorials for faster processing.

  • Property mode set to 100644
File size: 4.2 KB
Line 
1static double _hollow_cylinder_kernel(double q, double core_radius, double radius, 
2        double length, double dum);
3static double hollow_cylinder_analytical_2D_scaled(double q, double q_x, double q_y, double radius, double core_radius, double length, double sld,
4        double solvent_sld, double theta, double phi);
5static double hollow_cylinder_scaling(double integrand, double delrho, double volume);
6       
7double form_volume(double radius, double core_radius, double length);
8
9double Iq(double q, double radius, double core_radius, double length, double sld,
10        double solvent_sld);
11double Iqxy(double qx, double qy, double radius, double core_radius, double length, double sld,
12        double solvent_sld, double theta, double phi);
13
14// From Igor library
15static double _hollow_cylinder_kernel(double q, double core_radius, double radius, 
16        double length, double dum)
17{
18    double gamma,arg1,arg2,lam1,lam2,psi,sinarg,t2,retval;              //local variables
19   
20    gamma = core_radius/radius;
21    arg1 = q*radius*sqrt(1.0-dum*dum);          //1=shell (outer radius)
22    arg2 = q*core_radius*sqrt(1.0-dum*dum);                     //2=core (inner radius)
23    if (arg1 == 0.0){
24        lam1 = 1.0;
25    }else{
26        lam1 = 2.0*J1(arg1)/arg1;
27    }
28    if (arg2 == 0.0){
29        lam2 = 1.0;
30    }else{
31        lam2 = 2.0*J1(arg2)/arg2;
32    }
33    //Todo: Need to check psi behavior as gamma goes to 1.
34    psi = (lam1 -  gamma*gamma*lam2)/(1.0-gamma*gamma);         //SRK 10/19/00
35    sinarg = q*length*dum/2.0;
36    if (sinarg == 0.0){
37        t2 = 1.0;
38    }else{
39        t2 = sin(sinarg)/sinarg;
40    }
41
42    retval = psi*psi*t2*t2;
43   
44    return(retval);
45}
46static double hollow_cylinder_analytical_2D_scaled(double q, double q_x, double q_y, double radius, double core_radius, double length, double sld,
47        double solvent_sld, double theta, double phi) {
48        double cyl_x, cyl_y; //, cyl_z
49        //double q_z;
50        double vol, cos_val, delrho;
51        double answer;
52        //convert angle degree to radian
53        double pi = 4.0*atan(1.0);
54        theta = theta * pi/180.0;
55        phi = phi * pi/180.0;
56        delrho = solvent_sld - sld;
57
58        // Cylinder orientation
59        cyl_x = cos(theta) * cos(phi);
60        cyl_y = sin(theta);
61        //cyl_z = -cos(theta) * sin(phi);
62
63        // q vector
64        //q_z = 0;
65
66        // Compute the angle btw vector q and the
67        // axis of the cylinder
68        cos_val = cyl_x*q_x + cyl_y*q_y;// + cyl_z*q_z;
69
70        // The following test should always pass
71        if (fabs(cos_val)>1.0) {
72                //printf("core_shell_cylinder_analytical_2D: Unexpected error: cos(alpha)=%g\n", cos_val);
73                return NAN;
74        }
75
76        answer = _hollow_cylinder_kernel(q, core_radius, radius, length, cos_val);
77
78        vol = form_volume(radius, core_radius, length);
79        answer = hollow_cylinder_scaling(answer, delrho, vol);
80
81        return answer;
82}
83static double hollow_cylinder_scaling(double integrand, double delrho, double volume)
84{
85        double answer;
86        // Multiply by contrast^2
87        answer = integrand*delrho*delrho;
88
89        //normalize by cylinder volume
90        answer *= volume*volume;
91
92        //convert to [cm-1]
93        answer *= 1.0e-4;
94       
95        return answer;
96}
97
98
99double form_volume(double radius, double core_radius, double length)
100{
101        double pi = 4.0*atan(1.0);
102        double v_shell = pi*length*(radius*radius-core_radius*core_radius);
103        return(v_shell);
104}
105
106
107double Iq(double q, double radius, double core_radius, double length, double sld,
108        double solvent_sld)
109{
110    int i;
111        int nord=76;                    //order of integration
112        double lower,upper,zi, inter;           //upper and lower integration limits
113        double summ,answer,delrho;                      //running tally of integration
114        double norm,volume;     //final calculation variables
115       
116        if (core_radius >= radius || radius >= length) {
117                return NAN;
118        }
119       
120        delrho = solvent_sld - sld;
121        lower = 0.0;
122        upper = 1.0;            //limits of numerical integral
123
124        summ = 0.0;                     //initialize intergral
125        for(i=0;i<nord;i++) {
126                zi = ( Gauss76Z[i] * (upper-lower) + lower + upper )/2.0;
127                inter = Gauss76Wt[i] * _hollow_cylinder_kernel(q, core_radius, radius, length, zi);
128                summ += inter;
129        }
130       
131        norm = summ*(upper-lower)/2.0;
132        volume = form_volume(radius, core_radius, length);
133        answer = hollow_cylinder_scaling(norm, delrho, volume);
134       
135        return(answer);
136}
137
138double Iqxy(double qx, double qy, double radius, double core_radius, double length, double sld,
139        double solvent_sld, double theta, double phi)
140{
141        double q;
142        q = sqrt(qx*qx+qy*qy);
143        return hollow_cylinder_analytical_2D_scaled(q, qx/q, qy/q, radius, core_radius, length, sld, solvent_sld, theta, phi);
144}
Note: See TracBrowser for help on using the repository browser.