source: sasview/sansmodels/src/sans/models/c_models/stackeddisks.cpp @ e2f7b92

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

updated documents

  • Property mode set to 100644
File size: 8.1 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 *      TODO: add 2d
22 */
23
24#include <math.h>
25#include "models.hh"
26#include "parameters.hh"
27#include <stdio.h>
28using namespace std;
29
30extern "C" {
31        #include "libCylinder.h"
32        #include "libStructureFactor.h"
33        #include "stacked_disks.h"
34}
35
36StackedDisksModel :: StackedDisksModel() {
37        scale      = Parameter(1.0);
38        radius     = Parameter(3000.0, true);
39        radius.set_min(0.0);
40        core_thick  = Parameter(10.0, true);
41        core_thick.set_min(0.0);
42        layer_thick     = Parameter(15.0);
43        layer_thick.set_min(0.0);
44        core_sld = Parameter(4.0e-6);
45        layer_sld  = Parameter(-4.0e-7);
46        solvent_sld  = Parameter(5.0e-6);
47        n_stacking   = Parameter(1);
48        sigma_d   = Parameter(0);
49        background = Parameter(0.001);
50        axis_theta  = Parameter(0.0, true);
51        axis_phi    = Parameter(0.0, true);
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 StackedDisksModel :: operator()(double q) {
61        double dp[10];
62
63        // Fill parameter array for IGOR library
64        // Add the background after averaging
65        dp[0] = scale();
66        dp[1] = radius();
67        dp[2] = core_thick();
68        dp[3] = layer_thick();
69        dp[4] = core_sld();
70        dp[5] = layer_sld();
71        dp[6] = solvent_sld();
72        dp[7] = n_stacking();
73        dp[8] = sigma_d();
74        dp[9] = 0.0;
75
76        // Get the dispersion points for the radius
77        vector<WeightPoint> weights_radius;
78        radius.get_weights(weights_radius);
79
80        // Get the dispersion points for the core_thick
81        vector<WeightPoint> weights_core_thick;
82        core_thick.get_weights(weights_core_thick);
83
84        // Get the dispersion points for the layer_thick
85        vector<WeightPoint> weights_layer_thick;
86        layer_thick.get_weights(weights_layer_thick);
87
88        // Perform the computation, with all weight points
89        double sum = 0.0;
90        double norm = 0.0;
91
92        // Loop over length weight points
93        for(int i=0; i< (int)weights_radius.size(); i++) {
94                dp[1] = weights_radius[i].value;
95
96                // Loop over radius weight points
97                for(int j=0; j< (int)weights_core_thick.size(); j++) {
98                        dp[2] = weights_core_thick[j].value;
99
100                        // Loop over thickness weight points
101                        for(int k=0; k< (int)weights_layer_thick.size(); k++) {
102                                dp[3] = weights_layer_thick[k].value;
103
104                                sum += weights_radius[i].weight
105                                        * weights_core_thick[j].weight * weights_layer_thick[k].weight* StackedDiscs(dp, q);
106                                norm += weights_radius[i].weight
107                                        * weights_core_thick[j].weight* weights_layer_thick[k].weight;
108                        }
109                }
110        }
111        return sum/norm + background();
112}
113
114/**
115 * Function to evaluate 2D scattering function
116 * @param q_x: value of Q along x
117 * @param q_y: value of Q along y
118 * @return: function value
119 */
120double StackedDisksModel :: operator()(double qx, double qy) {
121        StackedDisksParameters dp;
122        // Fill parameter array
123        dp.scale      = scale();
124        dp.core_thick    = core_thick();
125        dp.radius         = radius();
126        dp.layer_thick  = layer_thick();
127        dp.core_sld   = core_sld();
128        dp.layer_sld  = layer_sld();
129        dp.solvent_sld= solvent_sld();
130        dp.n_stacking     = n_stacking();
131        dp.sigma_d   = sigma_d();
132        dp.background = 0.0;
133        dp.axis_theta = axis_theta();
134        dp.axis_phi   = axis_phi();
135
136        // Get the dispersion points for the length
137        vector<WeightPoint> weights_core_thick;
138        core_thick.get_weights(weights_core_thick);
139
140        // Get the dispersion points for the radius
141        vector<WeightPoint> weights_radius;
142        radius.get_weights(weights_radius);
143
144        // Get the dispersion points for the thickness
145        vector<WeightPoint> weights_layer_thick;
146        layer_thick.get_weights(weights_layer_thick);
147
148        // Get angular averaging for theta
149        vector<WeightPoint> weights_theta;
150        axis_theta.get_weights(weights_theta);
151
152        // Get angular averaging for phi
153        vector<WeightPoint> weights_phi;
154        axis_phi.get_weights(weights_phi);
155
156        // Perform the computation, with all weight points
157        double sum = 0.0;
158        double norm = 0.0;
159
160        // Loop over length weight points
161        for(int i=0; i< (int)weights_core_thick.size(); i++) {
162                dp.core_thick = weights_core_thick[i].value;
163
164                // Loop over radius weight points
165                for(int j=0; j< (int)weights_radius.size(); j++) {
166                        dp.radius = weights_radius[j].value;
167
168                                // Loop over thickness weight points
169                                for(int k=0; k< (int)weights_layer_thick.size(); k++) {
170                                dp.layer_thick = weights_layer_thick[k].value;
171
172                                        for(int l=0; l< (int)weights_theta.size(); l++) {
173                                        dp.axis_theta = weights_theta[l].value;
174
175                                                // Average over phi distribution
176                                                for(int m=0; m <(int)weights_phi.size(); m++) {
177                                                        dp.axis_phi = weights_phi[m].value;
178
179                                                        double _ptvalue = weights_core_thick[i].weight
180                                                                * weights_radius[j].weight
181                                                                * weights_layer_thick[k].weight
182                                                                * weights_theta[l].weight
183                                                                * weights_phi[m].weight
184                                                                * stacked_disks_analytical_2DXY(&dp, qx, qy);
185                                                        if (weights_theta.size()>1) {
186                                                                _ptvalue *= sin(weights_theta[l].value);
187                                                        }
188                                                        sum += _ptvalue;
189
190                                                        norm += weights_core_thick[i].weight
191                                                                * weights_radius[j].weight
192                                                                * weights_layer_thick[k].weight
193                                                                * weights_theta[l].weight
194                                                                * weights_phi[m].weight;
195                                                }
196                                }
197                        }
198                }
199        }
200        // Averaging in theta needs an extra normalization
201        // factor to account for the sin(theta) term in the
202        // integration (see documentation).
203        if (weights_theta.size()>1) norm = norm / asin(1.0);
204        return sum/norm + background();
205}
206
207/**
208 * Function to evaluate 2D scattering function
209 * @param pars: parameters of the triaxial ellipsoid
210 * @param q: q-value
211 * @param phi: angle phi
212 * @return: function value
213 */
214double StackedDisksModel :: evaluate_rphi(double q, double phi) {
215        double qx = q*cos(phi);
216        double qy = q*sin(phi);
217        return (*this).operator()(qx, qy);
218}
219/**
220 * Function to calculate effective radius
221 * @return: effective radius value
222 */
223double StackedDisksModel :: calculate_ER() {
224        StackedDisksParameters dp;
225
226        dp.core_thick    = core_thick();
227        dp.radius         = radius();
228        dp.layer_thick  = layer_thick();
229        dp.n_stacking     = n_stacking();
230
231        double rad_out = 0.0;
232        if (dp.n_stacking <= 0.0){
233                return rad_out;
234        }
235
236        // Perform the computation, with all weight points
237        double sum = 0.0;
238        double norm = 0.0;
239
240        // Get the dispersion points for the length
241        vector<WeightPoint> weights_core_thick;
242        core_thick.get_weights(weights_core_thick);
243
244        // Get the dispersion points for the radius
245        vector<WeightPoint> weights_radius;
246        radius.get_weights(weights_radius);
247
248        // Get the dispersion points for the thickness
249        vector<WeightPoint> weights_layer_thick;
250        layer_thick.get_weights(weights_layer_thick);
251
252        // Loop over major shell weight points
253        for(int i=0; i< (int)weights_core_thick.size(); i++) {
254                dp.core_thick = weights_core_thick[i].value;
255                for(int j=0; j< (int)weights_layer_thick.size(); j++) {
256                        dp.layer_thick = weights_layer_thick[j].value;
257                        for(int k=0; k< (int)weights_radius.size(); k++) {
258                                dp.radius = weights_radius[k].value;
259                                //Note: output of "DiamCyl(dp.length,dp.radius)" is DIAMETER.
260                                sum +=weights_core_thick[i].weight*weights_layer_thick[j].weight
261                                        * weights_radius[k].weight*DiamCyl(dp.n_stacking*(dp.layer_thick*2.0+dp.core_thick),dp.radius)/2.0;
262                                norm += weights_core_thick[i].weight*weights_layer_thick[j].weight* weights_radius[k].weight;
263                        }
264                }
265        }
266        if (norm != 0){
267                //return the averaged value
268                rad_out =  sum/norm;}
269        else{
270                //return normal value
271                //Note: output of "DiamCyl(dp.length,dp.radius)" is DIAMETER.
272                rad_out = DiamCyl(dp.n_stacking*(dp.layer_thick*2.0+dp.core_thick),dp.radius)/2.0;}
273
274        return rad_out;
275}
Note: See TracBrowser for help on using the repository browser.