Changeset 82c11d3 in sasview for sansmodels/src/c_models/stackeddisks.cpp
- Timestamp:
- Jan 5, 2012 6:24:51 PM (13 years ago)
- Branches:
- master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, costrafo411, magnetic_scatt, release-4.1.1, release-4.1.2, release-4.2.2, release_4.0.1, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
- Children:
- 20d91bd
- Parents:
- 98fdccd
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sansmodels/src/c_models/stackeddisks.cpp
r67424cd r82c11d3 23 23 24 24 #include <math.h> 25 #include "models.hh"26 25 #include "parameters.hh" 27 26 #include <stdio.h> 28 27 using namespace std; 28 #include "stacked_disks.h" 29 29 30 30 extern "C" { 31 #include "libCylinder.h" 32 #include "libStructureFactor.h" 33 #include "stacked_disks.h" 31 #include "libCylinder.h" 32 #include "libStructureFactor.h" 33 } 34 35 typedef struct { 36 double scale; 37 double radius; 38 double core_thick; 39 double layer_thick; 40 double core_sld; 41 double layer_sld; 42 double solvent_sld; 43 double n_stacking; 44 double sigma_d; 45 double background; 46 double axis_theta; 47 double axis_phi; 48 } StackedDisksParameters; 49 50 51 /** 52 * Function to evaluate 2D scattering function 53 * @param pars: parameters of the staked disks 54 * @param q: q-value 55 * @param q_x: q_x / q 56 * @param q_y: q_y / q 57 * @return: function value 58 */ 59 static double stacked_disks_analytical_2D_scaled(StackedDisksParameters *pars, double q, double q_x, double q_y) { 60 double cyl_x, cyl_y, cyl_z; 61 double q_z; 62 double alpha, vol, cos_val; 63 double d, dum, halfheight; 64 double answer; 65 66 67 68 // parallelepiped orientation 69 cyl_x = sin(pars->axis_theta) * cos(pars->axis_phi); 70 cyl_y = sin(pars->axis_theta) * sin(pars->axis_phi); 71 cyl_z = cos(pars->axis_theta); 72 73 // q vector 74 q_z = 0; 75 76 // Compute the angle btw vector q and the 77 // axis of the parallelepiped 78 cos_val = cyl_x*q_x + cyl_y*q_y + cyl_z*q_z; 79 80 // The following test should always pass 81 if (fabs(cos_val)>1.0) { 82 printf("parallel_ana_2D: Unexpected error: cos(alpha)>1\n"); 83 return 0; 84 } 85 86 // Note: cos(alpha) = 0 and 1 will get an 87 // undefined value from Stackdisc_kern 88 alpha = acos( cos_val ); 89 90 // Call the IGOR library function to get the kernel 91 d = 2 * pars->layer_thick + pars->core_thick; 92 halfheight = pars->core_thick/2.0; 93 dum =alpha ; 94 answer = Stackdisc_kern(q, pars->radius, pars->core_sld,pars->layer_sld, 95 pars->solvent_sld, halfheight, pars->layer_thick, dum, pars->sigma_d, d, pars->n_stacking)/sin(alpha); 96 97 // Multiply by contrast^2 98 //answer *= pars->contrast*pars->contrast; 99 100 //normalize by staked disks volume 101 vol = acos(-1.0) * pars->radius * pars->radius * d * pars->n_stacking; 102 answer /= vol; 103 104 //convert to [cm-1] 105 answer *= 1.0e8; 106 107 //Scale 108 answer *= pars->scale; 109 110 // add in the background 111 answer += pars->background; 112 113 return answer; 114 } 115 116 /** 117 * Function to evaluate 2D scattering function 118 * @param pars: parameters of the staked disks 119 * @param q: q-value 120 * @return: function value 121 */ 122 static double stacked_disks_analytical_2DXY(StackedDisksParameters *pars, double qx, double qy) { 123 double q; 124 q = sqrt(qx*qx+qy*qy); 125 return stacked_disks_analytical_2D_scaled(pars, q, qx/q, qy/q); 34 126 } 35 127 36 128 StackedDisksModel :: StackedDisksModel() { 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 129 scale = Parameter(1.0); 130 radius = Parameter(3000.0, true); 131 radius.set_min(0.0); 132 core_thick = Parameter(10.0, true); 133 core_thick.set_min(0.0); 134 layer_thick = Parameter(15.0); 135 layer_thick.set_min(0.0); 136 core_sld = Parameter(4.0e-6); 137 layer_sld = Parameter(-4.0e-7); 138 solvent_sld = Parameter(5.0e-6); 139 n_stacking = Parameter(1); 140 sigma_d = Parameter(0); 141 background = Parameter(0.001); 142 axis_theta = Parameter(0.0, true); 143 axis_phi = Parameter(0.0, true); 52 144 } 53 145 … … 59 151 */ 60 152 double StackedDisksModel :: operator()(double q) { 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 153 double dp[10]; 154 155 // Fill parameter array for IGOR library 156 // Add the background after averaging 157 dp[0] = scale(); 158 dp[1] = radius(); 159 dp[2] = core_thick(); 160 dp[3] = layer_thick(); 161 dp[4] = core_sld(); 162 dp[5] = layer_sld(); 163 dp[6] = solvent_sld(); 164 dp[7] = n_stacking(); 165 dp[8] = sigma_d(); 166 dp[9] = 0.0; 167 168 // Get the dispersion points for the radius 169 vector<WeightPoint> weights_radius; 170 radius.get_weights(weights_radius); 171 172 // Get the dispersion points for the core_thick 173 vector<WeightPoint> weights_core_thick; 174 core_thick.get_weights(weights_core_thick); 175 176 // Get the dispersion points for the layer_thick 177 vector<WeightPoint> weights_layer_thick; 178 layer_thick.get_weights(weights_layer_thick); 179 180 // Perform the computation, with all weight points 181 double sum = 0.0; 182 double norm = 0.0; 183 double vol = 0.0; 184 185 // Loop over length weight points 186 for(int i=0; i< (int)weights_radius.size(); i++) { 187 dp[1] = weights_radius[i].value; 188 189 // Loop over radius weight points 190 for(int j=0; j< (int)weights_core_thick.size(); j++) { 191 dp[2] = weights_core_thick[j].value; 192 193 // Loop over thickness weight points 194 for(int k=0; k< (int)weights_layer_thick.size(); k++) { 195 dp[3] = weights_layer_thick[k].value; 196 //Un-normalize by volume 197 sum += weights_radius[i].weight 198 * weights_core_thick[j].weight * weights_layer_thick[k].weight* StackedDiscs(dp, q) 199 *pow(weights_radius[i].value,2)*(weights_core_thick[j].value+2*weights_layer_thick[k].value); 200 //Find average volume 201 vol += weights_radius[i].weight 202 * weights_core_thick[j].weight * weights_layer_thick[k].weight 203 *pow(weights_radius[i].value,2)*(weights_core_thick[j].value+2*weights_layer_thick[k].value); 204 norm += weights_radius[i].weight 205 * weights_core_thick[j].weight* weights_layer_thick[k].weight; 206 } 207 } 208 } 209 if (vol != 0.0 && norm != 0.0) { 210 //Re-normalize by avg volume 211 sum = sum/(vol/norm);} 212 213 return sum/norm + background(); 122 214 } 123 215 … … 129 221 */ 130 222 double StackedDisksModel :: operator()(double qx, double qy) { 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 223 StackedDisksParameters dp; 224 // Fill parameter array 225 dp.scale = scale(); 226 dp.core_thick = core_thick(); 227 dp.radius = radius(); 228 dp.layer_thick = layer_thick(); 229 dp.core_sld = core_sld(); 230 dp.layer_sld = layer_sld(); 231 dp.solvent_sld= solvent_sld(); 232 dp.n_stacking = n_stacking(); 233 dp.sigma_d = sigma_d(); 234 dp.background = 0.0; 235 dp.axis_theta = axis_theta(); 236 dp.axis_phi = axis_phi(); 237 238 // Get the dispersion points for the length 239 vector<WeightPoint> weights_core_thick; 240 core_thick.get_weights(weights_core_thick); 241 242 // Get the dispersion points for the radius 243 vector<WeightPoint> weights_radius; 244 radius.get_weights(weights_radius); 245 246 // Get the dispersion points for the thickness 247 vector<WeightPoint> weights_layer_thick; 248 layer_thick.get_weights(weights_layer_thick); 249 250 // Get angular averaging for theta 251 vector<WeightPoint> weights_theta; 252 axis_theta.get_weights(weights_theta); 253 254 // Get angular averaging for phi 255 vector<WeightPoint> weights_phi; 256 axis_phi.get_weights(weights_phi); 257 258 // Perform the computation, with all weight points 259 double sum = 0.0; 260 double norm = 0.0; 261 double norm_vol = 0.0; 262 double vol = 0.0; 263 264 // Loop over length weight points 265 for(int i=0; i< (int)weights_core_thick.size(); i++) { 266 dp.core_thick = weights_core_thick[i].value; 267 268 // Loop over radius weight points 269 for(int j=0; j< (int)weights_radius.size(); j++) { 270 dp.radius = weights_radius[j].value; 271 272 // Loop over thickness weight points 273 for(int k=0; k< (int)weights_layer_thick.size(); k++) { 274 dp.layer_thick = weights_layer_thick[k].value; 275 276 for(int l=0; l< (int)weights_theta.size(); l++) { 277 dp.axis_theta = weights_theta[l].value; 278 279 // Average over phi distribution 280 for(int m=0; m <(int)weights_phi.size(); m++) { 281 dp.axis_phi = weights_phi[m].value; 282 283 //Un-normalize by volume 284 double _ptvalue = weights_core_thick[i].weight 285 * weights_radius[j].weight 286 * weights_layer_thick[k].weight 287 * weights_theta[l].weight 288 * weights_phi[m].weight 289 * stacked_disks_analytical_2DXY(&dp, qx, qy) 290 *pow(weights_radius[j].value,2)*(weights_core_thick[i].value+2*weights_layer_thick[k].value); 291 if (weights_theta.size()>1) { 292 _ptvalue *= fabs(sin(weights_theta[l].value)); 293 } 294 sum += _ptvalue; 295 //Find average volume 296 vol += weights_radius[j].weight 297 * weights_core_thick[i].weight * weights_layer_thick[k].weight 298 *pow(weights_radius[j].value,2)*(weights_core_thick[i].value+2*weights_layer_thick[k].value); 299 //Find norm for volume 300 norm_vol += weights_radius[j].weight 301 * weights_core_thick[i].weight * weights_layer_thick[k].weight; 302 303 norm += weights_core_thick[i].weight 304 * weights_radius[j].weight 305 * weights_layer_thick[k].weight 306 * weights_theta[l].weight 307 * weights_phi[m].weight; 308 } 309 } 310 } 311 } 312 } 313 // Averaging in theta needs an extra normalization 314 // factor to account for the sin(theta) term in the 315 // integration (see documentation). 316 if (weights_theta.size()>1) norm = norm / asin(1.0); 317 if (vol != 0.0 && norm_vol != 0.0) { 318 //Re-normalize by avg volume 319 sum = sum/(vol/norm_vol);} 320 return sum/norm + background(); 229 321 } 230 322 … … 237 329 */ 238 330 double StackedDisksModel :: evaluate_rphi(double q, double phi) { 239 240 241 331 double qx = q*cos(phi); 332 double qy = q*sin(phi); 333 return (*this).operator()(qx, qy); 242 334 } 243 335 /** … … 246 338 */ 247 339 double StackedDisksModel :: calculate_ER() { 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 } 340 StackedDisksParameters dp; 341 342 dp.core_thick = core_thick(); 343 dp.radius = radius(); 344 dp.layer_thick = layer_thick(); 345 dp.n_stacking = n_stacking(); 346 347 double rad_out = 0.0; 348 if (dp.n_stacking <= 0.0){ 349 return rad_out; 350 } 351 352 // Perform the computation, with all weight points 353 double sum = 0.0; 354 double norm = 0.0; 355 356 // Get the dispersion points for the length 357 vector<WeightPoint> weights_core_thick; 358 core_thick.get_weights(weights_core_thick); 359 360 // Get the dispersion points for the radius 361 vector<WeightPoint> weights_radius; 362 radius.get_weights(weights_radius); 363 364 // Get the dispersion points for the thickness 365 vector<WeightPoint> weights_layer_thick; 366 layer_thick.get_weights(weights_layer_thick); 367 368 // Loop over major shell weight points 369 for(int i=0; i< (int)weights_core_thick.size(); i++) { 370 dp.core_thick = weights_core_thick[i].value; 371 for(int j=0; j< (int)weights_layer_thick.size(); j++) { 372 dp.layer_thick = weights_layer_thick[j].value; 373 for(int k=0; k< (int)weights_radius.size(); k++) { 374 dp.radius = weights_radius[k].value; 375 //Note: output of "DiamCyl(dp.length,dp.radius)" is DIAMETER. 376 sum +=weights_core_thick[i].weight*weights_layer_thick[j].weight 377 * weights_radius[k].weight*DiamCyl(dp.n_stacking*(dp.layer_thick*2.0+dp.core_thick),dp.radius)/2.0; 378 norm += weights_core_thick[i].weight*weights_layer_thick[j].weight* weights_radius[k].weight; 379 } 380 } 381 } 382 if (norm != 0){ 383 //return the averaged value 384 rad_out = sum/norm;} 385 else{ 386 //return normal value 387 //Note: output of "DiamCyl(dp.length,dp.radius)" is DIAMETER. 388 rad_out = DiamCyl(dp.n_stacking*(dp.layer_thick*2.0+dp.core_thick),dp.radius)/2.0;} 389 390 return rad_out; 391 }
Note: See TracChangeset
for help on using the changeset viewer.