source: sasview/sansmodels/src/sans/models/c_models/spheroid.cpp @ ef70686

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since ef70686 was 4628e31, checked in by Jae Cho <jhjcho@…>, 14 years ago

changed the unit of angles into degrees

  • Property mode set to 100644
File size: 9.9 KB
Line 
1/**
2        This software was developed by the University of Tennessee as part of the
3        Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
4        project funded by the US National Science Foundation.
5
6        If you use DANSE applications to do scientific research that leads to
7        publication, we ask that you acknowledge the use of the software with the
8        following sentence:
9
10        "This work benefited from DANSE software developed under NSF award DMR-0520547."
11
12        copyright 2008, University of Tennessee
13 */
14
15/**
16 * Scattering model classes
17 * The classes use the IGOR library found in
18 *   sansmodels/src/libigor
19 *
20 *      TODO: refactor so that we pull in the old sansmodels.c_extensions
21 */
22
23#include <math.h>
24#include "models.hh"
25#include "parameters.hh"
26#include <stdio.h>
27using namespace std;
28
29extern "C" {
30        #include "libCylinder.h"
31        #include "libStructureFactor.h"
32        #include "spheroid.h"
33}
34
35CoreShellEllipsoidModel :: CoreShellEllipsoidModel() {
36        scale      = Parameter(1.0);
37        equat_core     = Parameter(200.0, true);
38        equat_core.set_min(0.0);
39        polar_core     = Parameter(20.0, true);
40        polar_core.set_min(0.0);
41        equat_shell   = Parameter(250.0, true);
42        equat_shell.set_min(0.0);
43        polar_shell    = Parameter(30.0, true);
44        polar_shell.set_min(0.0);
45        sld_core   = Parameter(2e-6);
46        sld_shell  = Parameter(1e-6);
47        sld_solvent = Parameter(6.3e-6);
48        background = Parameter(0.0);
49        axis_theta  = Parameter(0.0, true);
50        axis_phi    = Parameter(0.0, true);
51
52}
53
54/**
55 * Function to evaluate 1D scattering function
56 * The NIST IGOR library is used for the actual calculation.
57 * @param q: q-value
58 * @return: function value
59 */
60double CoreShellEllipsoidModel :: operator()(double q) {
61        double dp[9];
62
63        // Fill parameter array for IGOR library
64        // Add the background after averaging
65        dp[0] = scale();
66        dp[1] = equat_core();
67        dp[2] = polar_core();
68        dp[3] = equat_shell();
69        dp[4] = polar_shell();
70        dp[5] = sld_core();
71        dp[6] = sld_shell();
72        dp[7] = sld_solvent();
73        dp[8] = 0.0;
74
75        // Get the dispersion points for the major core
76        vector<WeightPoint> weights_equat_core;
77        equat_core.get_weights(weights_equat_core);
78
79        // Get the dispersion points for the minor core
80        vector<WeightPoint> weights_polar_core;
81        polar_core.get_weights(weights_polar_core);
82
83        // Get the dispersion points for the major shell
84        vector<WeightPoint> weights_equat_shell;
85        equat_shell.get_weights(weights_equat_shell);
86
87        // Get the dispersion points for the minor_shell
88        vector<WeightPoint> weights_polar_shell;
89        polar_shell.get_weights(weights_polar_shell);
90
91
92        // Perform the computation, with all weight points
93        double sum = 0.0;
94        double norm = 0.0;
95        double vol = 0.0;
96
97        // Loop over major core weight points
98        for(int i=0; i<(int)weights_equat_core.size(); i++) {
99                dp[1] = weights_equat_core[i].value;
100
101                // Loop over minor core weight points
102                for(int j=0; j<(int)weights_polar_core.size(); j++) {
103                        dp[2] = weights_polar_core[j].value;
104
105                        // Loop over major shell weight points
106                        for(int k=0; k<(int)weights_equat_shell.size(); k++) {
107                                dp[3] = weights_equat_shell[k].value;
108
109                                // Loop over minor shell weight points
110                                for(int l=0; l<(int)weights_polar_shell.size(); l++) {
111                                        dp[4] = weights_polar_shell[l].value;
112                                        //Un-normalize  by volume
113                                        sum += weights_equat_core[i].weight* weights_polar_core[j].weight * weights_equat_shell[k].weight
114                                                * weights_polar_shell[l].weight * OblateForm(dp, q)
115                                                * pow(weights_equat_shell[k].value,2)*weights_polar_shell[l].value;
116                                        //Find average volume
117                                        vol += weights_equat_core[i].weight* weights_polar_core[j].weight
118                                                * weights_equat_shell[k].weight
119                                                * weights_polar_shell[l].weight
120                                                * pow(weights_equat_shell[k].value,2)*weights_polar_shell[l].value;
121                                        norm += weights_equat_core[i].weight* weights_polar_core[j].weight * weights_equat_shell[k].weight
122                                                        * weights_polar_shell[l].weight;
123                                }
124                        }
125                }
126        }
127        if (vol != 0.0 && norm != 0.0) {
128                //Re-normalize by avg volume
129                sum = sum/(vol/norm);}
130        return sum/norm + background();
131}
132
133/**
134 * Function to evaluate 2D scattering function
135 * @param q_x: value of Q along x
136 * @param q_y: value of Q along y
137 * @return: function value
138 */
139/*
140double OblateModel :: operator()(double qx, double qy) {
141        double q = sqrt(qx*qx + qy*qy);
142
143        return (*this).operator()(q);
144}
145*/
146
147/**
148 * Function to evaluate 2D scattering function
149 * @param pars: parameters of the oblate
150 * @param q: q-value
151 * @param phi: angle phi
152 * @return: function value
153 */
154double CoreShellEllipsoidModel :: evaluate_rphi(double q, double phi) {
155        double qx = q*cos(phi);
156        double qy = q*sin(phi);
157        return (*this).operator()(qx, qy);
158}
159
160/**
161 * Function to evaluate 2D scattering function
162 * @param q_x: value of Q along x
163 * @param q_y: value of Q along y
164 * @return: function value
165 */
166double CoreShellEllipsoidModel :: operator()(double qx, double qy) {
167        SpheroidParameters dp;
168        // Fill parameter array
169        dp.scale      = scale();
170        dp.equat_core = equat_core();
171        dp.polar_core = polar_core();
172        dp.equat_shell = equat_shell();
173        dp.polar_shell = polar_shell();
174        dp.sld_core = sld_core();
175        dp.sld_shell = sld_shell();
176        dp.sld_solvent = sld_solvent();
177        dp.background = 0.0;
178        dp.axis_theta = axis_theta();
179        dp.axis_phi = axis_phi();
180
181        // Get the dispersion points for the major core
182        vector<WeightPoint> weights_equat_core;
183        equat_core.get_weights(weights_equat_core);
184
185        // Get the dispersion points for the minor core
186        vector<WeightPoint> weights_polar_core;
187        polar_core.get_weights(weights_polar_core);
188
189        // Get the dispersion points for the major shell
190        vector<WeightPoint> weights_equat_shell;
191        equat_shell.get_weights(weights_equat_shell);
192
193        // Get the dispersion points for the minor shell
194        vector<WeightPoint> weights_polar_shell;
195        polar_shell.get_weights(weights_polar_shell);
196
197
198        // Get angular averaging for theta
199        vector<WeightPoint> weights_theta;
200        axis_theta.get_weights(weights_theta);
201
202        // Get angular averaging for phi
203        vector<WeightPoint> weights_phi;
204        axis_phi.get_weights(weights_phi);
205
206        // Perform the computation, with all weight points
207        double sum = 0.0;
208        double norm = 0.0;
209        double norm_vol = 0.0;
210        double vol = 0.0;
211        double pi = 4.0*atan(1.0);
212        // Loop over major core weight points
213        for(int i=0; i< (int)weights_equat_core.size(); i++) {
214                dp.equat_core = weights_equat_core[i].value;
215
216                // Loop over minor core weight points
217                for(int j=0; j< (int)weights_polar_core.size(); j++) {
218                        dp.polar_core = weights_polar_core[j].value;
219
220                        // Loop over major shell weight points
221                        for(int k=0; k< (int)weights_equat_shell.size(); k++) {
222                                dp.equat_shell = weights_equat_shell[i].value;
223
224                                // Loop over minor shell weight points
225                                for(int l=0; l< (int)weights_polar_shell.size(); l++) {
226                                        dp.polar_shell = weights_polar_shell[l].value;
227
228                                        // Average over theta distribution
229                                        for(int m=0; m< (int)weights_theta.size(); m++) {
230                                                dp.axis_theta = weights_theta[m].value;
231
232                                                // Average over phi distribution
233                                                for(int n=0; n< (int)weights_phi.size(); n++) {
234                                                        dp.axis_phi = weights_phi[n].value;
235                                                        //Un-normalize by volume
236                                                        double _ptvalue = weights_equat_core[i].weight *weights_polar_core[j].weight
237                                                                * weights_equat_shell[k].weight * weights_polar_shell[l].weight
238                                                                * weights_theta[m].weight
239                                                                * weights_phi[n].weight
240                                                                * spheroid_analytical_2DXY(&dp, qx, qy)
241                                                                * pow(weights_equat_shell[k].value,2)*weights_polar_shell[l].value;
242                                                        if (weights_theta.size()>1) {
243                                                                _ptvalue *= fabs(sin(weights_theta[m].value*pi/180.0));
244                                                        }
245                                                        sum += _ptvalue;
246                                                        //Find average volume
247                                                        vol += weights_equat_shell[k].weight
248                                                                * weights_polar_shell[l].weight
249                                                                * pow(weights_equat_shell[k].value,2)*weights_polar_shell[l].value;
250                                                        //Find norm for volume
251                                                        norm_vol += weights_equat_shell[k].weight
252                                                                * weights_polar_shell[l].weight;
253
254                                                        norm += weights_equat_core[i].weight *weights_polar_core[j].weight
255                                                                * weights_equat_shell[k].weight * weights_polar_shell[l].weight
256                                                                * weights_theta[m].weight * weights_phi[n].weight;
257                                                }
258                                        }
259                                }
260                        }
261                }
262        }
263        // Averaging in theta needs an extra normalization
264        // factor to account for the sin(theta) term in the
265        // integration (see documentation).
266        if (weights_theta.size()>1) norm = norm / asin(1.0);
267
268        if (vol != 0.0 && norm_vol != 0.0) {
269                //Re-normalize by avg volume
270                sum = sum/(vol/norm_vol);}
271
272        return sum/norm + background();
273}
274
275/**
276 * Function to calculate effective radius
277 * @return: effective radius value
278 */
279double CoreShellEllipsoidModel :: calculate_ER() {
280        SpheroidParameters dp;
281
282        dp.equat_shell = equat_shell();
283        dp.polar_shell = polar_shell();
284
285        double rad_out = 0.0;
286
287        // Perform the computation, with all weight points
288        double sum = 0.0;
289        double norm = 0.0;
290
291        // Get the dispersion points for the major shell
292        vector<WeightPoint> weights_equat_shell;
293        equat_shell.get_weights(weights_equat_shell);
294
295        // Get the dispersion points for the minor shell
296        vector<WeightPoint> weights_polar_shell;
297        polar_shell.get_weights(weights_polar_shell);
298
299        // Loop over major shell weight points
300        for(int i=0; i< (int)weights_equat_shell.size(); i++) {
301                dp.equat_shell = weights_equat_shell[i].value;
302                for(int k=0; k< (int)weights_polar_shell.size(); k++) {
303                        dp.polar_shell = weights_polar_shell[k].value;
304                        //Note: output of "DiamEllip(dp.polar_shell,dp.equat_shell)" is DIAMETER.
305                        sum +=weights_equat_shell[i].weight
306                                * weights_polar_shell[k].weight*DiamEllip(dp.polar_shell,dp.equat_shell)/2.0;
307                        norm += weights_equat_shell[i].weight* weights_polar_shell[k].weight;
308                }
309        }
310        if (norm != 0){
311                //return the averaged value
312                rad_out =  sum/norm;}
313        else{
314                //return normal value
315                //Note: output of "DiamEllip(dp.polar_shell,dp.equat_shell)" is DIAMETER.
316                rad_out = DiamEllip(dp.polar_shell,dp.equat_shell)/2.0;}
317
318        return rad_out;
319}
Note: See TracBrowser for help on using the repository browser.