source: sasview/sansmodels/src/c_models/fuzzysphere.cpp @ 046af80

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 046af80 was 0ba3b08, checked in by Mathieu Doucet <doucetm@…>, 13 years ago

refactored bunch of models

  • Property mode set to 100644
File size: 4.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#include <math.h>
17#include "parameters.hh"
18#include <stdio.h>
19#include <stdlib.h>
20using namespace std;
21#include "fuzzysphere.h"
22
23extern "C" {
24#include "libSphere.h"
25}
26
27// scattering from a uniform sphere w/ fuzzy surface
28// Modified from FuzzySpheres in libigor/libSphere.c without polydispersion: JHC
29static double fuzzysphere_kernel(double dp[], double q){
30  double pi,x,xr;
31  double radius,sldSph,sldSolv,scale,bkg,delrho,fuzziness,f2,bes,vol,f;   //my local names
32
33  pi = 4.0*atan(1.0);
34  x= q;
35  scale = dp[0];
36  radius = dp[1];
37  fuzziness = dp[2];
38  sldSph = dp[3];
39  sldSolv = dp[4];
40  bkg = dp[5];
41  delrho=sldSph-sldSolv;
42
43  xr = x*radius;
44  //handle xr==0 separately
45  if(xr == 0.0){
46    bes = 1.0;
47  }else{
48    bes = 3.0*(sin(xr)-xr*cos(xr))/(xr*xr*xr);
49  }
50  vol = 4.0*pi/3.0*radius*radius*radius;
51  f = vol*bes*delrho;   // [=] A
52  f *= exp(-0.5*fuzziness*fuzziness*x*x);
53  // normalize to single particle volume, convert to 1/cm
54  f2 = f * f / vol * 1.0e8;   // [=] 1/cm
55
56  f2 *= scale;
57  f2 += bkg;
58
59    return(f2); //scale, and add in the background
60}
61
62FuzzySphereModel :: FuzzySphereModel() {
63        scale      = Parameter(0.01);
64        radius     = Parameter(60.0, true);
65        radius.set_min(0.0);
66        fuzziness  = Parameter(10.0);
67        fuzziness.set_min(0.0);
68        sldSph   = Parameter(1.0e-6);
69        sldSolv   = Parameter(3.0e-6);
70        background = Parameter(0.001);
71}
72
73/**
74 * Function to evaluate 1D scattering function
75 * The NIST IGOR library is used for the actual calculation.
76 * @param q: q-value
77 * @return: function value
78 */
79double FuzzySphereModel :: operator()(double q) {
80        double dp[6];
81
82        // Fill parameter array for IGOR library
83        // Add the background after averaging
84        dp[0] = scale();
85        dp[1] = radius();
86        dp[2] = fuzziness();
87        dp[3] = sldSph();
88        dp[4] = sldSolv();
89        dp[5] = 0.0;
90
91        // Get the dispersion points for the radius
92        vector<WeightPoint> weights_radius;
93        radius.get_weights(weights_radius);
94
95        // Get the dispersion points for the fuzziness
96        vector<WeightPoint> weights_fuzziness;
97        fuzziness.get_weights(weights_fuzziness);
98
99        // Perform the computation, with all weight points
100        double sum = 0.0;
101        double norm = 0.0;
102        double norm_vol = 0.0;
103        double vol = 0.0;
104
105        // Loop over radius weight points
106        for(size_t i=0; i<weights_radius.size(); i++) {
107                dp[1] = weights_radius[i].value;
108                // Loop over fuzziness weight points
109                for(size_t j=0; j<weights_fuzziness.size(); j++) {
110                        dp[2] = weights_fuzziness[j].value;
111
112                        //Un-normalize SphereForm by volume
113                        sum += weights_radius[i].weight * weights_fuzziness[j].weight
114                                * fuzzysphere_kernel(dp, q) * pow(weights_radius[i].value,3);
115                        //Find average volume : Note the fuzziness has no contribution to the volume
116                        vol += weights_radius[i].weight
117                                * pow(weights_radius[i].value,3);
118
119                        norm += weights_radius[i].weight * weights_fuzziness[j].weight;
120                        norm_vol += weights_radius[i].weight;
121                }
122        }
123
124        if (vol != 0.0 && norm_vol != 0.0) {
125                //Re-normalize by avg volume
126                sum = sum/(vol/norm_vol);}
127        return sum/norm + background();
128}
129
130/**
131 * Function to evaluate 2D scattering function
132 * @param q_x: value of Q along x
133 * @param q_y: value of Q along y
134 * @return: function value
135 */
136double FuzzySphereModel :: operator()(double qx, double qy) {
137        double q = sqrt(qx*qx + qy*qy);
138        return (*this).operator()(q);
139}
140
141/**
142 * Function to evaluate 2D scattering function
143 * @param pars: parameters of the sphere
144 * @param q: q-value
145 * @param phi: angle phi
146 * @return: function value
147 */
148double FuzzySphereModel :: evaluate_rphi(double q, double phi) {
149        return (*this).operator()(q);
150}
151
152/**
153 * Function to calculate effective radius
154 * @return: effective radius value
155 */
156double FuzzySphereModel :: calculate_ER() {
157        double rad_out = 0.0;
158
159        // Perform the computation, with all weight points
160        double sum = 0.0;
161        double norm = 0.0;
162
163        // Get the dispersion points for the radius
164        // No need to consider the fuzziness.
165        vector<WeightPoint> weights_radius;
166        radius.get_weights(weights_radius);
167        // Loop over radius weight points to average the radius value
168        for(size_t i=0; i<weights_radius.size(); i++) {
169                sum += weights_radius[i].weight
170                        * weights_radius[i].value;
171                norm += weights_radius[i].weight;
172        }
173        if (norm != 0){
174                //return the averaged value
175                rad_out =  sum/norm;}
176        else{
177                //return normal value
178                rad_out = radius();}
179
180        return rad_out;
181}
Note: See TracBrowser for help on using the repository browser.