source: sasmodels/sasmodels/models/core_shell_parallelepiped.c @ 44bd2be

core_shell_microgelscostrafo411magnetic_modelrelease_v0.94release_v0.95ticket-1257-vesicle-productticket_1156ticket_1265_superballticket_822_more_unit_tests
Last change on this file since 44bd2be was 44bd2be, checked in by gonzalezm, 8 years ago

Added core_shell_parallelepiped moded (but very doubtful)

  • Property mode set to 100644
File size: 10.4 KB
Line 
1double form_volume(double a_side, double b_side, double c_side, 
2                   double arim_thickness, double brim_thickness, double crim_thickness);
3double Iq(double q, double core_sld, double arim_sld, double brim_sld, double crim_sld,
4          double solvent_sld, double a_side, double b_side, double c_side,
5          double arim_thickness, double brim_thickness, double crim_thickness);
6double Iqxy(double qx, double qy, double core_sld, double arim_sld, double brim_sld,
7            double crim_sld, double solvent_sld, double a_side, double b_side,
8            double c_side, double arim_thickness, double brim_thickness,
9            double crim_thickness, double theta, double phi, double psi);
10
11double form_volume(double a_side, double b_side, double c_side, 
12                   double arim_thickness, double brim_thickness, double crim_thickness)
13{
14    //return a_side * b_side * c_side;
15    return a_side * b_side * c_side + 
16           2.0 * arim_thickness * b_side * c_side + 
17           2.0 * brim_thickness * a_side * c_side +
18           2.0 * crim_thickness * a_side * b_side;
19}
20
21double Iq(double q,
22    double core_sld,
23    double arim_sld,
24    double brim_sld,
25    double crim_sld,
26    double solvent_sld,
27    double a_side,
28    double b_side,
29    double c_side,
30    double arim_thickness,
31    double brim_thickness,
32    double crim_thickness)
33{
34    // Code converted from functions CSPPKernel and CSParallelepiped in libCylinder.c_scaled
35    // Did not understand the code completely, it should be rechecked (Miguel Gonzalez)
36   
37    double t1, t2, t3, t4, tmp, answer;   
38    double mu = q * b_side;
39   
40    //calculate volume before rescaling (in original code, but not used)
41    //double vol = form_volume(a_side, b_side, c_side, arim_thickness, brim_thickness, crim_thickness);         
42    //double vol = a_side * b_side * c_side +
43    //       2.0 * arim_thickness * b_side * c_side +
44    //       2.0 * brim_thickness * a_side * c_side +
45    //       2.0 * crim_thickness * a_side * b_side;
46   
47    // Scale sides by B
48    double a_scaled = a_side / b_side;
49    double c_scaled = c_side / b_side;
50    double arim_scaled = arim_thickness / b_side;
51    double brim_scaled = brim_thickness / b_side;
52       
53    // DelRho values (note that drC is not used later)       
54        double dr0 = core_sld-solvent_sld;
55        double drA = arim_sld-solvent_sld;
56        double drB = brim_sld-solvent_sld;
57        //double drC = crim_sld-solvent_sld;
58
59    //Order of integration
60    int nordi=76;                               
61    int nordj=76;
62   
63    // outer integral (with nordi gauss points), integration limits = 0, 1
64    double summ = 0; //initialize integral
65
66    for( int i=0; i<nordi; i++) {
67               
68        // inner integral (with nordj gauss points), integration limits = 0, 1
69       
70        double summj = 0.0;
71            double sigma = 0.5 * ( Gauss76Z[i] + 1.0 );         
72               
73            for(int j=0; j<nordj; j++) {
74
75            double uu = 0.5 * ( Gauss76Z[j] + 1.0 );
76            double mudum = mu * sqrt(1.0-sigma*sigma);
77
78                double Vin = a_side * b_side * c_side;
79                //double Vot = (a_side * b_side * c_side +
80            //            2.0 * arim_thickness * b_side * c_side +
81            //            2.0 * a_side * brim_thickness * c_side +
82            //            2.0 * a_side * b_side * crim_thickness);
83                double V1 = (2.0 * arim_thickness * b_side * c_side);    // incorrect V1 (aa*bb*cc+2*ta*bb*cc)
84                double V2 = (2.0 * a_side * brim_thickness * c_side);    // incorrect V2(aa*bb*cc+2*aa*tb*cc)
85       
86            // ta and tb correspond to the definitions in CSPPKernel, but they don't make sense to me (MG)
87            // the a_scaled in the definition of tb was present in CSPPKernel in libCylinder.c,
88            // while in cspkernel in csparallelepiped.cpp (used for the 2D), all the definitions
89            // for ta, tb, tc use also A + 2*rim_thickness (but not scaled by B!!!)           
90            double ta = (a_scaled+2.0*arim_thickness)/b_side; 
91            double tb = (a_scaled+2.0*brim_thickness)/b_side;
92   
93                double arg1 = (0.5*mudum*a_scaled) * sin(0.5*M_PI*uu);
94                double arg2 = (0.5*mudum) * cos(0.5*M_PI*uu);
95                double arg3=  (0.5*mudum*ta) * sin(0.5*M_PI*uu);
96                double arg4=  (0.5*mudum*tb) * cos(0.5*M_PI*uu);
97
98                if(arg1==0.0){
99                        t1 = 1.0;
100                } else {
101                        t1 = (sin(arg1)/arg1);                //defn for CSPP model sin(arg1)/arg1    test:  (sin(arg1)/arg1)*(sin(arg1)/arg1)   
102                }
103                if(arg2==0.0){
104                        t2 = 1.0;
105                } else {
106                        t2 = (sin(arg2)/arg2);           //defn for CSPP model sin(arg2)/arg2   test: (sin(arg2)/arg2)*(sin(arg2)/arg2)   
107                }       
108                if(arg3==0.0){
109                        t3 = 1.0;
110                } else {
111                        t3 = sin(arg3)/arg3;
112                }
113                if(arg4==0.0){
114                        t4 = 1.0;
115                } else {
116                        t4 = sin(arg4)/arg4;
117                }
118           
119            // Expression in libCylinder.c (neither drC nor Vot are used)
120                tmp =( dr0*t1*t2*Vin + drA*(t3-t1)*t2*V1+ drB*t1*(t4-t2)*V2 )*( dr0*t1*t2*Vin + drA*(t3-t1)*t2*V1+ drB*t1*(t4-t2)*V2 );   //  correct FF : square of sum of phase factors           
121           
122            // To note also that in csparallelepiped.cpp, there is a function called
123            // cspkernel, which seems to make more sense and has the following comment:
124            //   This expression is different from NIST/IGOR package (I strongly believe the IGOR is wrong!!!). 10/15/2010.
125            //   tmp =( dr0*tmp1*tmp2*tmp3*Vin + drA*(tmpt1-tmp1)*tmp2*tmp3*V1+ drB*tmp1*(tmpt2-tmp2)*tmp3*V2 + drC*tmp1*tmp2*(tmpt3-tmp3)*V3)*
126            //   ( dr0*tmp1*tmp2*tmp3*Vin + drA*(tmpt1-tmp1)*tmp2*tmp3*V1+ drB*tmp1*(tmpt2-tmp2)*tmp3*V2 + drC*tmp1*tmp2*(tmpt3-tmp3)*V3);   //  correct FF : square of sum of phase factors
127            // This is the function called by csparallelepiped_analytical_2D_scaled,
128            // while CSParallelepipedModel calls CSParallelepiped in libCylinder.c       
129           
130            summj += Gauss76Wt[j] * tmp;
131
132        }
133               
134        // value of the inner integral
135        answer = 0.5 * summj;
136
137                // finish the outer integral
138                double arg = 0.5 * mu* c_scaled *sigma;
139                if ( arg == 0.0 ) {
140                        answer *= 1.0;
141                } else {
142                answer *= sin(arg)*sin(arg)/arg/arg;
143                }
144               
145                // now sum up the outer integral
146                summ += Gauss76Wt[i] * answer;
147
148    }
149   
150        answer = 0.5 * summ;
151
152        //convert from [1e-12 A-1] to [cm-1]
153        answer *= 1.0e-4;
154       
155        return answer;
156}
157
158double Iqxy(double qx, double qy,
159    double core_sld,
160    double arim_sld,
161    double brim_sld,
162    double crim_sld,
163    double solvent_sld,
164    double a_side,
165    double b_side,
166    double c_side,
167    double arim_thickness,
168    double brim_thickness,
169    double crim_thickness,
170    double theta,
171    double phi,
172    double psi)
173{
174    double tmp1, tmp2, tmp3, tmpt1, tmpt2, tmpt3;   
175
176    double q = sqrt(qx*qx+qy*qy);
177    double qx_scaled = qx/q;
178    double qy_scaled = qy/q;
179
180    // Convert angles given in degrees to radians
181    theta *= M_PI_180;
182    phi   *= M_PI_180;
183    psi   *= M_PI_180;
184   
185    // Parallelepiped c axis orientation
186    double cparallel_x = cos(theta) * cos(phi);
187    double cparallel_y = sin(theta);
188   
189    // Compute angle between q and parallelepiped axis
190    double cos_val_c = cparallel_x*qx_scaled + cparallel_y*qy_scaled;// + cparallel_z*qz;
191
192    // Parallelepiped a axis orientation
193    double parallel_x = -cos(phi)*sin(psi) * sin(theta)+sin(phi)*cos(psi);
194    double parallel_y = sin(psi)*cos(theta);
195    double cos_val_a = parallel_x*qx_scaled + parallel_y*qy_scaled;
196
197    // Parallelepiped b axis orientation
198    double bparallel_x = -sin(theta)*cos(psi)*cos(phi)-sin(psi)*sin(phi);
199    double bparallel_y = cos(theta)*cos(psi);
200    double cos_val_b = bparallel_x*qx_scaled + bparallel_y*qy_scaled;
201
202    // The following tests should always pass
203    if (fabs(cos_val_c)>1.0) {
204      //printf("parallel_ana_2D: Unexpected error: cos(alpha)>1\n");
205      cos_val_c = 1.0;
206    }
207    if (fabs(cos_val_a)>1.0) {
208      //printf("parallel_ana_2D: Unexpected error: cos(alpha)>1\n");
209      cos_val_a = 1.0;
210    }
211    if (fabs(cos_val_b)>1.0) {
212      //printf("parallel_ana_2D: Unexpected error: cos(alpha)>1\n");
213      cos_val_b = 1.0;
214    }
215   
216    // cspkernel in csparallelepiped recoded here
217    double dr0 = core_sld-solvent_sld;
218        double drA = arim_sld-solvent_sld;
219        double drB = brim_sld-solvent_sld;
220        double drC = crim_sld-solvent_sld;
221        double Vin = a_side * b_side * c_side;
222    // As for the 1D case, Vot is not used
223        //double Vot = (a_side * b_side * c_side +
224    //              2.0 * arim_thickness * b_side * c_side +
225    //              2.0 * a_side * brim_thickness * c_side +
226    //              2.0 * a_side * b_side * crim_thickness);
227        double V1 = (2.0 * arim_thickness * b_side * c_side);    // incorrect V1 (aa*bb*cc+2*ta*bb*cc)
228        double V2 = (2.0 * a_side * brim_thickness * c_side);    // incorrect V2(aa*bb*cc+2*aa*tb*cc)
229    double V3 = (2.0 * a_side * b_side * crim_thickness);
230    // The definitions of ta, tb, tc are not the same as in the 1D case because there is no
231    // the scaling by B. The use of a_side for the 3 of them seems clearly a mistake to me,
232    // but for the moment I let it like this until understanding better the code.
233        double ta = a_side + 2.0*arim_thickness;
234    double tb = a_side + 2.0*brim_thickness;
235    double tc = a_side + 2.0*crim_thickness;
236    //handle arg=0 separately, as sin(t)/t -> 1 as t->0
237    double argA = 0.5*q*a_side*cos_val_a;
238    double argB = 0.5*q*b_side*cos_val_b;
239    double argC = 0.5*q*c_side*cos_val_c;
240    double argtA = 0.5*q*ta*cos_val_a;
241    double argtB = 0.5*q*tb*cos_val_b;
242    double argtC = 0.5*q*tc*cos_val_c;
243   
244    if(argA==0.0) {
245        tmp1 = 1.0;
246    } else {
247        tmp1 = sin(argA)/argA;
248    }
249    if (argB==0.0) {
250        tmp2 = 1.0;
251    } else {
252        tmp2 = sin(argB)/argB;
253    }
254    if (argC==0.0) {
255        tmp3 = 1.0;
256    } else {
257        tmp3 = sin(argC)/argC;
258    }
259    if(argtA==0.0) {
260        tmpt1 = 1.0;
261    } else {
262        tmpt1 = sin(argtA)/argtA;
263    }
264    if (argtB==0.0) {
265        tmpt2 = 1.0;
266    } else {
267        tmpt2 = sin(argtB)/argtB;
268    }
269    if (argtC==0.0) {
270        tmpt3 = 1.0;
271    } else {
272        tmpt3 = sin(argtC)*sin(argtC)/argtC/argtC;
273    }
274
275    // f uses Vin, V1, V2, and V3 and it seems to have more sense than the value computed
276    // in the 1D code, but should be checked!
277    double f = ( dr0*tmp1*tmp2*tmp3*Vin + drA*(tmpt1-tmp1)*tmp2*tmp3*V1 + 
278               drB*tmp1*(tmpt2-tmp2)*tmp3*V2 + drC*tmp1*tmp2*(tmpt3-tmp3)*V3);
279   
280    return 1.0e-4 * f * f;
281}
Note: See TracBrowser for help on using the repository browser.