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

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 6e93a02 was c451be9, checked in by Jae Cho <jhjcho@…>, 15 years ago

corrections on the definition of polydispersity as suggested by steve K: should be normalized by average volume

  • Property mode set to 100644
File size: 9.8 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        contrast   = Parameter(1e-6);
46        sld_solvent = Parameter(6.3e-6);
47        background = Parameter(0.0);
48        axis_theta  = Parameter(0.0, true);
49        axis_phi    = Parameter(0.0, true);
50
51}
52
53/**
54 * Function to evaluate 1D scattering function
55 * The NIST IGOR library is used for the actual calculation.
56 * @param q: q-value
57 * @return: function value
58 */
59double CoreShellEllipsoidModel :: operator()(double q) {
60        double dp[8];
61
62        // Fill parameter array for IGOR library
63        // Add the background after averaging
64        dp[0] = scale();
65        dp[1] = equat_core();
66        dp[2] = polar_core();
67        dp[3] = equat_shell();
68        dp[4] = polar_shell();
69        dp[5] = contrast();
70        dp[6] = sld_solvent();
71        dp[7] = 0.0;
72
73        // Get the dispersion points for the major core
74        vector<WeightPoint> weights_equat_core;
75        equat_core.get_weights(weights_equat_core);
76
77        // Get the dispersion points for the minor core
78        vector<WeightPoint> weights_polar_core;
79        polar_core.get_weights(weights_polar_core);
80
81        // Get the dispersion points for the major shell
82        vector<WeightPoint> weights_equat_shell;
83        equat_shell.get_weights(weights_equat_shell);
84
85        // Get the dispersion points for the minor_shell
86        vector<WeightPoint> weights_polar_shell;
87        polar_shell.get_weights(weights_polar_shell);
88
89
90        // Perform the computation, with all weight points
91        double sum = 0.0;
92        double norm = 0.0;
93        double vol = 0.0;
94
95        // Loop over major core weight points
96        for(int i=0; i<(int)weights_equat_core.size(); i++) {
97                dp[1] = weights_equat_core[i].value;
98
99                // Loop over minor core weight points
100                for(int j=0; j<(int)weights_polar_core.size(); j++) {
101                        dp[2] = weights_polar_core[j].value;
102
103                        // Loop over major shell weight points
104                        for(int k=0; k<(int)weights_equat_shell.size(); k++) {
105                                dp[3] = weights_equat_shell[k].value;
106
107                                // Loop over minor shell weight points
108                                for(int l=0; l<(int)weights_polar_shell.size(); l++) {
109                                        dp[4] = weights_polar_shell[l].value;
110                                        //Un-normalize  by volume
111                                        sum += weights_equat_core[i].weight* weights_polar_core[j].weight * weights_equat_shell[k].weight
112                                                * weights_polar_shell[l].weight * ProlateForm(dp, q)
113                                                * pow(weights_equat_shell[k].value,2)*weights_polar_shell[l].value;
114                                        //Find average volume
115                                        vol += weights_equat_core[i].weight* weights_polar_core[j].weight
116                                                * weights_equat_shell[k].weight
117                                                * weights_polar_shell[l].weight
118                                                * pow(weights_equat_shell[k].value,2)*weights_polar_shell[l].value;
119                                        norm += weights_equat_core[i].weight* weights_polar_core[j].weight * weights_equat_shell[k].weight
120                                                        * weights_polar_shell[l].weight;
121                                }
122                        }
123                }
124        }
125        if (vol != 0.0 && norm != 0.0) {
126                //Re-normalize by avg volume
127                sum = sum/(vol/norm);}
128        return sum/norm + background();
129}
130
131/**
132 * Function to evaluate 2D scattering function
133 * @param q_x: value of Q along x
134 * @param q_y: value of Q along y
135 * @return: function value
136 */
137/*
138double OblateModel :: operator()(double qx, double qy) {
139        double q = sqrt(qx*qx + qy*qy);
140
141        return (*this).operator()(q);
142}
143*/
144
145/**
146 * Function to evaluate 2D scattering function
147 * @param pars: parameters of the oblate
148 * @param q: q-value
149 * @param phi: angle phi
150 * @return: function value
151 */
152double CoreShellEllipsoidModel :: evaluate_rphi(double q, double phi) {
153        double qx = q*cos(phi);
154        double qy = q*sin(phi);
155        return (*this).operator()(qx, qy);
156}
157
158/**
159 * Function to evaluate 2D scattering function
160 * @param q_x: value of Q along x
161 * @param q_y: value of Q along y
162 * @return: function value
163 */
164double CoreShellEllipsoidModel :: operator()(double qx, double qy) {
165        SpheroidParameters dp;
166        // Fill parameter array
167        dp.scale      = scale();
168        dp.equat_core = equat_core();
169        dp.polar_core = polar_core();
170        dp.equat_shell = equat_shell();
171        dp.polar_shell = polar_shell();
172        dp.contrast = contrast();
173        dp.sld_solvent = sld_solvent();
174        dp.background = 0.0;
175        dp.axis_theta = axis_theta();
176        dp.axis_phi = axis_phi();
177
178        // Get the dispersion points for the major core
179        vector<WeightPoint> weights_equat_core;
180        equat_core.get_weights(weights_equat_core);
181
182        // Get the dispersion points for the minor core
183        vector<WeightPoint> weights_polar_core;
184        polar_core.get_weights(weights_polar_core);
185
186        // Get the dispersion points for the major shell
187        vector<WeightPoint> weights_equat_shell;
188        equat_shell.get_weights(weights_equat_shell);
189
190        // Get the dispersion points for the minor shell
191        vector<WeightPoint> weights_polar_shell;
192        polar_shell.get_weights(weights_polar_shell);
193
194
195        // Get angular averaging for theta
196        vector<WeightPoint> weights_theta;
197        axis_theta.get_weights(weights_theta);
198
199        // Get angular averaging for phi
200        vector<WeightPoint> weights_phi;
201        axis_phi.get_weights(weights_phi);
202
203        // Perform the computation, with all weight points
204        double sum = 0.0;
205        double norm = 0.0;
206        double norm_vol = 0.0;
207        double vol = 0.0;
208
209        // Loop over major core weight points
210        for(int i=0; i< (int)weights_equat_core.size(); i++) {
211                dp.equat_core = weights_equat_core[i].value;
212
213                // Loop over minor core weight points
214                for(int j=0; j< (int)weights_polar_core.size(); j++) {
215                        dp.polar_core = weights_polar_core[j].value;
216
217                        // Loop over major shell weight points
218                        for(int k=0; k< (int)weights_equat_shell.size(); k++) {
219                                dp.equat_shell = weights_equat_shell[i].value;
220
221                                // Loop over minor shell weight points
222                                for(int l=0; l< (int)weights_polar_shell.size(); l++) {
223                                        dp.polar_shell = weights_polar_shell[l].value;
224
225                                        // Average over theta distribution
226                                        for(int m=0; m< (int)weights_theta.size(); m++) {
227                                                dp.axis_theta = weights_theta[m].value;
228
229                                                // Average over phi distribution
230                                                for(int n=0; n< (int)weights_phi.size(); n++) {
231                                                        dp.axis_phi = weights_phi[n].value;
232                                                        //Un-normalize by volume
233                                                        double _ptvalue = weights_equat_core[i].weight *weights_polar_core[j].weight
234                                                                * weights_equat_shell[k].weight * weights_polar_shell[l].weight
235                                                                * weights_theta[m].weight
236                                                                * weights_phi[n].weight
237                                                                * spheroid_analytical_2DXY(&dp, qx, qy)
238                                                                * pow(weights_equat_shell[k].value,2)*weights_polar_shell[l].value;
239                                                        if (weights_theta.size()>1) {
240                                                                _ptvalue *= sin(weights_theta[m].value);
241                                                        }
242                                                        sum += _ptvalue;
243                                                        //Find average volume
244                                                        vol += weights_equat_shell[k].weight
245                                                                * weights_polar_shell[l].weight
246                                                                * pow(weights_equat_shell[k].value,2)*weights_polar_shell[l].value;
247                                                        //Find norm for volume
248                                                        norm_vol += weights_equat_shell[k].weight
249                                                                * weights_polar_shell[l].weight;
250
251                                                        norm += weights_equat_core[i].weight *weights_polar_core[j].weight
252                                                                * weights_equat_shell[k].weight * weights_polar_shell[l].weight
253                                                                * weights_theta[m].weight * weights_phi[n].weight;
254                                                }
255                                        }
256                                }
257                        }
258                }
259        }
260        // Averaging in theta needs an extra normalization
261        // factor to account for the sin(theta) term in the
262        // integration (see documentation).
263        if (weights_theta.size()>1) norm = norm / asin(1.0);
264
265        if (vol != 0.0 && norm_vol != 0.0) {
266                //Re-normalize by avg volume
267                sum = sum/(vol/norm_vol);}
268
269        return sum/norm + background();
270}
271
272/**
273 * Function to calculate effective radius
274 * @return: effective radius value
275 */
276double CoreShellEllipsoidModel :: calculate_ER() {
277        SpheroidParameters dp;
278
279        dp.equat_shell = equat_shell();
280        dp.polar_shell = polar_shell();
281
282        double rad_out = 0.0;
283
284        // Perform the computation, with all weight points
285        double sum = 0.0;
286        double norm = 0.0;
287
288        // Get the dispersion points for the major shell
289        vector<WeightPoint> weights_equat_shell;
290        equat_shell.get_weights(weights_equat_shell);
291
292        // Get the dispersion points for the minor shell
293        vector<WeightPoint> weights_polar_shell;
294        polar_shell.get_weights(weights_polar_shell);
295
296        // Loop over major shell weight points
297        for(int i=0; i< (int)weights_equat_shell.size(); i++) {
298                dp.equat_shell = weights_equat_shell[i].value;
299                for(int k=0; k< (int)weights_polar_shell.size(); k++) {
300                        dp.polar_shell = weights_polar_shell[k].value;
301                        //Note: output of "DiamEllip(dp.polar_shell,dp.equat_shell)" is DIAMETER.
302                        sum +=weights_equat_shell[i].weight
303                                * weights_polar_shell[k].weight*DiamEllip(dp.polar_shell,dp.equat_shell)/2.0;
304                        norm += weights_equat_shell[i].weight* weights_polar_shell[k].weight;
305                }
306        }
307        if (norm != 0){
308                //return the averaged value
309                rad_out =  sum/norm;}
310        else{
311                //return normal value
312                //Note: output of "DiamEllip(dp.polar_shell,dp.equat_shell)" is DIAMETER.
313                rad_out = DiamEllip(dp.polar_shell,dp.equat_shell)/2.0;}
314
315        return rad_out;
316}
Note: See TracBrowser for help on using the repository browser.