source: sasview/sansmodels/src/sans/models/c_models/ellipticalcylinder.cpp @ 7ef319e

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

updated documents

  • Property mode set to 100644
File size: 7.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 "elliptical_cylinder.h"
33}
34
35EllipticalCylinderModel :: EllipticalCylinderModel() {
36        scale      = Parameter(1.0);
37        r_minor    = Parameter(20.0, true);
38        r_minor.set_min(0.0);
39        r_ratio    = Parameter(1.5, true);
40        r_ratio.set_min(0.0);
41        length     = Parameter(400.0, true);
42        length.set_min(0.0);
43        contrast   = Parameter(3.e-6);
44        background = Parameter(0.0);
45        cyl_theta  = Parameter(1.57, true);
46        cyl_phi    = Parameter(0.0, true);
47        cyl_psi    = Parameter(0.0, true);
48}
49
50/**
51 * Function to evaluate 1D scattering function
52 * The NIST IGOR library is used for the actual calculation.
53 * @param q: q-value
54 * @return: function value
55 */
56double EllipticalCylinderModel :: operator()(double q) {
57        double dp[6];
58
59        dp[0] = scale();
60        dp[1] = r_minor();
61        dp[2] = r_ratio();
62        dp[3] = length();
63        dp[4] = contrast();
64        dp[5] = 0.0;
65
66        // Get the dispersion points for the r_minor
67        vector<WeightPoint> weights_rad;
68        r_minor.get_weights(weights_rad);
69
70        // Get the dispersion points for the r_ratio
71        vector<WeightPoint> weights_rat;
72        r_ratio.get_weights(weights_rat);
73
74        // Get the dispersion points for the length
75        vector<WeightPoint> weights_len;
76        length.get_weights(weights_len);
77
78        // Perform the computation, with all weight points
79        double sum = 0.0;
80        double norm = 0.0;
81
82        // Loop over r_minor weight points
83        for(int i=0; i<weights_rad.size(); i++) {
84                dp[1] = weights_rad[i].value;
85
86                // Loop over r_ratio weight points
87                for(int j=0; j<weights_rat.size(); j++) {
88                        dp[2] = weights_rat[j].value;
89
90                        // Loop over length weight points
91                        for(int k=0; k<weights_len.size(); k++) {
92                                dp[3] = weights_len[k].value;
93
94                                sum += weights_rad[i].weight
95                                        * weights_len[k].weight
96                                        * weights_rat[j].weight
97                                        * EllipCyl20(dp, q);
98                                norm += weights_rad[i].weight
99                                * weights_len[k].weight
100                                * weights_rat[j].weight;
101                        }
102                }
103        }
104        return sum/norm + background();
105}
106
107/**
108 * Function to evaluate 2D scattering function
109 * @param q_x: value of Q along x
110 * @param q_y: value of Q along y
111 * @return: function value
112 */
113double EllipticalCylinderModel :: operator()(double qx, double qy) {
114        EllipticalCylinderParameters dp;
115        // Fill parameter array
116        dp.scale      = scale();
117        dp.r_minor    = r_minor();
118        dp.r_ratio    = r_ratio();
119        dp.length     = length();
120        dp.contrast   = contrast();
121        dp.background = 0.0;
122        dp.cyl_theta  = cyl_theta();
123        dp.cyl_phi    = cyl_phi();
124        dp.cyl_psi    = cyl_psi();
125
126        // Get the dispersion points for the r_minor
127        vector<WeightPoint> weights_rad;
128        r_minor.get_weights(weights_rad);
129
130        // Get the dispersion points for the r_ratio
131        vector<WeightPoint> weights_rat;
132        r_ratio.get_weights(weights_rat);
133
134        // Get the dispersion points for the length
135        vector<WeightPoint> weights_len;
136        length.get_weights(weights_len);
137
138        // Get angular averaging for theta
139        vector<WeightPoint> weights_theta;
140        cyl_theta.get_weights(weights_theta);
141
142        // Get angular averaging for phi
143        vector<WeightPoint> weights_phi;
144        cyl_phi.get_weights(weights_phi);
145
146        // Get angular averaging for psi
147        vector<WeightPoint> weights_psi;
148        cyl_psi.get_weights(weights_psi);
149
150        // Perform the computation, with all weight points
151        double sum = 0.0;
152        double norm = 0.0;
153
154        // Loop over minor radius weight points
155        for(int i=0; i<weights_rad.size(); i++) {
156                dp.r_minor = weights_rad[i].value;
157
158
159                // Loop over length weight points
160                for(int j=0; j<weights_len.size(); j++) {
161                        dp.length = weights_len[j].value;
162
163                        // Loop over r_ration weight points
164                        for(int m=0; m<weights_rat.size(); m++) {
165                                dp.r_ratio = weights_rat[m].value;
166
167                        // Average over theta distribution
168                        for(int k=0; k<weights_theta.size(); k++) {
169                                dp.cyl_theta = weights_theta[k].value;
170
171                                // Average over phi distribution
172                                for(int l=0; l<weights_phi.size(); l++) {
173                                        dp.cyl_phi = weights_phi[l].value;
174
175                                // Average over phi distribution
176                                for(int o=0; o<weights_psi.size(); o++) {
177                                        dp.cyl_psi = weights_psi[o].value;
178
179                                        double _ptvalue = weights_rad[i].weight
180                                                * weights_len[j].weight
181                                                * weights_rat[m].weight
182                                                * weights_theta[k].weight
183                                                * weights_phi[l].weight
184                                                * weights_psi[o].weight
185                                                * elliptical_cylinder_analytical_2DXY(&dp, qx, qy);
186                                        if (weights_theta.size()>1) {
187                                                _ptvalue *= sin(weights_theta[k].value);
188                                        }
189                                        sum += _ptvalue;
190
191                                        norm += weights_rad[i].weight
192                                                * weights_len[j].weight
193                                                * weights_rat[m].weight
194                                                * weights_theta[k].weight
195                                                * weights_phi[l].weight
196                                                * weights_psi[o].weight;
197
198                                }
199                                }
200                        }
201                        }
202                }
203        }
204        // Averaging in theta needs an extra normalization
205        // factor to account for the sin(theta) term in the
206        // integration (see documentation).
207        if (weights_theta.size()>1) norm = norm / asin(1.0);
208        return sum/norm + background();
209}
210
211/**
212 * Function to evaluate 2D scattering function
213 * @param pars: parameters of the cylinder
214 * @param q: q-value
215 * @param phi: angle phi
216 * @return: function value
217 */
218double EllipticalCylinderModel :: evaluate_rphi(double q, double phi) {
219        double qx = q*cos(phi);
220        double qy = q*sin(phi);
221        return (*this).operator()(qx, qy);
222}
223/**
224 * Function to calculate effective radius
225 * @return: effective radius value
226 */
227double EllipticalCylinderModel :: calculate_ER() {
228        EllipticalCylinderParameters dp;
229        dp.r_minor    = r_minor();
230        dp.r_ratio    = r_ratio();
231        dp.length     = length();
232        double rad_out = 0.0;
233        double pi = 4.0*atan(1.0);
234        double suf_rad = sqrt(dp.r_minor*dp.r_minor*dp.r_ratio);
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 r_minor
241        vector<WeightPoint> weights_rad;
242        r_minor.get_weights(weights_rad);
243
244        // Get the dispersion points for the r_ratio
245        vector<WeightPoint> weights_rat;
246        r_ratio.get_weights(weights_rat);
247
248        // Get the dispersion points for the length
249        vector<WeightPoint> weights_len;
250        length.get_weights(weights_len);
251
252        // Loop over minor radius weight points
253        for(int i=0; i<weights_rad.size(); i++) {
254                dp.r_minor = weights_rad[i].value;
255
256                // Loop over length weight points
257                for(int j=0; j<weights_len.size(); j++) {
258                        dp.length = weights_len[j].value;
259
260                        // Loop over r_ration weight points
261                        for(int m=0; m<weights_rat.size(); m++) {
262                                dp.r_ratio = weights_rat[m].value;
263                                //Calculate surface averaged radius
264                                suf_rad = sqrt(dp.r_minor * dp.r_minor * dp.r_ratio);
265
266                                //Note: output of "DiamCyl(dp.length,dp.radius)" is DIAMETER.
267                                sum +=weights_rad[i].weight *weights_len[j].weight
268                                        * weights_rat[m].weight*DiamCyl(dp.length, suf_rad)/2.0;
269                                norm += weights_rad[i].weight *weights_len[j].weight* weights_rat[m].weight;
270                        }
271                }
272        }
273        if (norm != 0){
274                //return the averaged value
275                rad_out =  sum/norm;}
276        else{
277                //return normal value
278                //Note: output of "DiamCyl(dp.length,dp.radius)" is DIAMETER.
279                rad_out = DiamCyl(dp.length, suf_rad)/2.0;}
280
281        return rad_out;
282}
Note: See TracBrowser for help on using the repository browser.