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

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 5be36bb was 5eb9154, checked in by Jae Cho <jhjcho@…>, 15 years ago

calculation of the effective radius are added

  • Property mode set to 100644
File size: 8.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
94        // Loop over major core weight points
95        for(int i=0; i<(int)weights_equat_core.size(); i++) {
96                dp[1] = weights_equat_core[i].value;
97
98                // Loop over minor core weight points
99                for(int j=0; j<(int)weights_polar_core.size(); j++) {
100                        dp[2] = weights_polar_core[j].value;
101
102                        // Loop over major shell weight points
103                        for(int k=0; k<(int)weights_equat_shell.size(); k++) {
104                                dp[3] = weights_equat_shell[k].value;
105
106                                // Loop over minor shell weight points
107                                for(int l=0; l<(int)weights_polar_shell.size(); l++) {
108                                        dp[4] = weights_polar_shell[l].value;
109
110                                        sum += weights_equat_core[i].weight* weights_polar_core[j].weight * weights_equat_shell[k].weight
111                                                * weights_polar_shell[l].weight * ProlateForm(dp, q);
112                                        norm += weights_equat_core[i].weight* weights_polar_core[j].weight * weights_equat_shell[k].weight
113                                                        * weights_polar_shell[l].weight;
114                                }
115                        }
116                }
117        }
118        return sum/norm + background();
119}
120
121/**
122 * Function to evaluate 2D scattering function
123 * @param q_x: value of Q along x
124 * @param q_y: value of Q along y
125 * @return: function value
126 */
127/*
128double OblateModel :: operator()(double qx, double qy) {
129        double q = sqrt(qx*qx + qy*qy);
130
131        return (*this).operator()(q);
132}
133*/
134
135/**
136 * Function to evaluate 2D scattering function
137 * @param pars: parameters of the oblate
138 * @param q: q-value
139 * @param phi: angle phi
140 * @return: function value
141 */
142double CoreShellEllipsoidModel :: evaluate_rphi(double q, double phi) {
143        double qx = q*cos(phi);
144        double qy = q*sin(phi);
145        return (*this).operator()(qx, qy);
146}
147
148/**
149 * Function to evaluate 2D scattering function
150 * @param q_x: value of Q along x
151 * @param q_y: value of Q along y
152 * @return: function value
153 */
154double CoreShellEllipsoidModel :: operator()(double qx, double qy) {
155        SpheroidParameters dp;
156        // Fill parameter array
157        dp.scale      = scale();
158        dp.equat_core = equat_core();
159        dp.polar_core = polar_core();
160        dp.equat_shell = equat_shell();
161        dp.polar_shell = polar_shell();
162        dp.contrast = contrast();
163        dp.sld_solvent = sld_solvent();
164        dp.background = 0.0;
165        dp.axis_theta = axis_theta();
166        dp.axis_phi = axis_phi();
167
168        // Get the dispersion points for the major core
169        vector<WeightPoint> weights_equat_core;
170        equat_core.get_weights(weights_equat_core);
171
172        // Get the dispersion points for the minor core
173        vector<WeightPoint> weights_polar_core;
174        polar_core.get_weights(weights_polar_core);
175
176        // Get the dispersion points for the major shell
177        vector<WeightPoint> weights_equat_shell;
178        equat_shell.get_weights(weights_equat_shell);
179
180        // Get the dispersion points for the minor shell
181        vector<WeightPoint> weights_polar_shell;
182        polar_shell.get_weights(weights_polar_shell);
183
184
185        // Get angular averaging for theta
186        vector<WeightPoint> weights_theta;
187        axis_theta.get_weights(weights_theta);
188
189        // Get angular averaging for phi
190        vector<WeightPoint> weights_phi;
191        axis_phi.get_weights(weights_phi);
192
193        // Perform the computation, with all weight points
194        double sum = 0.0;
195        double norm = 0.0;
196
197        // Loop over major core weight points
198        for(int i=0; i< (int)weights_equat_core.size(); i++) {
199                dp.equat_core = weights_equat_core[i].value;
200
201                // Loop over minor core weight points
202                for(int j=0; j< (int)weights_polar_core.size(); j++) {
203                        dp.polar_core = weights_polar_core[j].value;
204
205                        // Loop over major shell weight points
206                        for(int k=0; k< (int)weights_equat_shell.size(); k++) {
207                                dp.equat_shell = weights_equat_shell[i].value;
208
209                                // Loop over minor shell weight points
210                                for(int l=0; l< (int)weights_polar_shell.size(); l++) {
211                                        dp.polar_shell = weights_polar_shell[l].value;
212
213                                        // Average over theta distribution
214                                        for(int m=0; m< (int)weights_theta.size(); m++) {
215                                                dp.axis_theta = weights_theta[m].value;
216
217                                                // Average over phi distribution
218                                                for(int n=0; n< (int)weights_phi.size(); n++) {
219                                                        dp.axis_phi = weights_phi[n].value;
220
221                                                        double _ptvalue = weights_equat_core[i].weight *weights_polar_core[j].weight
222                                                                * weights_equat_shell[k].weight * weights_polar_shell[l].weight
223                                                                * weights_theta[m].weight
224                                                                * weights_phi[n].weight
225                                                                * spheroid_analytical_2DXY(&dp, qx, qy);
226                                                        if (weights_theta.size()>1) {
227                                                                _ptvalue *= sin(weights_theta[m].value);
228                                                        }
229                                                        sum += _ptvalue;
230
231                                                        norm += weights_equat_core[i].weight *weights_polar_core[j].weight
232                                                                * weights_equat_shell[k].weight * weights_polar_shell[l].weight
233                                                                * weights_theta[m].weight * weights_phi[n].weight;
234                                                }
235                                        }
236                                }
237                        }
238                }
239        }
240        // Averaging in theta needs an extra normalization
241        // factor to account for the sin(theta) term in the
242        // integration (see documentation).
243        if (weights_theta.size()>1) norm = norm / asin(1.0);
244        return sum/norm + background();
245}
246
247/**
248 * Function to calculate effective radius
249 * @param pars: parameters of the sphere
250 * @return: effective radius value
251 */
252double CoreShellEllipsoidModel :: calculate_ER() {
253        SpheroidParameters dp;
254
255        dp.equat_shell = equat_shell();
256        dp.polar_shell = polar_shell();
257
258        double rad_out = 0.0;
259
260        // Perform the computation, with all weight points
261        double sum = 0.0;
262        double norm = 0.0;
263
264        // Get the dispersion points for the major shell
265        vector<WeightPoint> weights_equat_shell;
266        equat_shell.get_weights(weights_equat_shell);
267
268        // Get the dispersion points for the minor shell
269        vector<WeightPoint> weights_polar_shell;
270        polar_shell.get_weights(weights_polar_shell);
271
272        // Loop over major shell weight points
273        for(int i=0; i< (int)weights_equat_shell.size(); i++) {
274                dp.equat_shell = weights_equat_shell[i].value;
275                for(int k=0; k< (int)weights_polar_shell.size(); k++) {
276                        dp.polar_shell = weights_polar_shell[k].value;
277                        //Note: output of "DiamEllip(dp.polar_shell,dp.equat_shell)" is DIAMETER.
278                        sum +=weights_equat_shell[i].weight
279                                * weights_polar_shell[k].weight*DiamEllip(dp.polar_shell,dp.equat_shell)/2.0;
280                        norm += weights_equat_shell[i].weight* weights_polar_shell[k].weight;
281                }
282        }
283        if (norm != 0){
284                //return the averaged value
285                rad_out =  sum/norm;}
286        else{
287                //return normal value
288                //Note: output of "DiamEllip(dp.polar_shell,dp.equat_shell)" is DIAMETER.
289                rad_out = DiamEllip(dp.polar_shell,dp.equat_shell)/2.0;}
290
291        return rad_out;
292}
Note: See TracBrowser for help on using the repository browser.