Changeset 82c11d3 in sasview for sansmodels/src/c_models
- 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
- Location:
- sansmodels/src/c_models
- Files:
-
- 1 added
- 1 deleted
- 24 edited
Legend:
- Unmodified
- Added
- Removed
-
sansmodels/src/c_models/binaryHS.cpp
r67424cd r82c11d3 21 21 22 22 #include <math.h> 23 #include "models.hh"24 23 #include "parameters.hh" 25 24 #include <stdio.h> 26 25 using namespace std; 26 #include "binaryHS.h" 27 27 28 28 extern "C" { 29 #include "libSphere.h" 30 #include "binaryHS.h" 29 #include "libSphere.h" 31 30 } 32 31 33 32 BinaryHSModel :: BinaryHSModel() { 34 33 35 36 37 38 39 40 41 42 43 44 34 l_radius = Parameter(160.0, true); 35 l_radius.set_min(0.0); 36 s_radius = Parameter(25.0, true); 37 s_radius.set_min(0.0); 38 vol_frac_ls = Parameter(0.2); 39 vol_frac_ss = Parameter(0.1); 40 ls_sld = Parameter(3.5e-6); 41 ss_sld = Parameter(5e-7); 42 solvent_sld = Parameter(6.36e-6); 43 background = Parameter(0.0); 45 44 } 46 45 … … 52 51 */ 53 52 double BinaryHSModel :: operator()(double q) { 54 53 double dp[8]; 55 54 56 57 58 59 60 61 62 63 64 65 55 // Fill parameter array for IGOR library 56 // Add the background after averaging 57 dp[0] = l_radius(); 58 dp[1] = s_radius(); 59 dp[2] = vol_frac_ls(); 60 dp[3] = vol_frac_ss(); 61 dp[4] = ls_sld(); 62 dp[5] = ss_sld(); 63 dp[6] = solvent_sld(); 64 dp[7] = 0.0; 66 65 67 66 68 69 70 67 // Get the dispersion points for the large radius 68 vector<WeightPoint> weights_l_radius; 69 l_radius.get_weights(weights_l_radius); 71 70 72 73 74 71 // Get the dispersion points for the small radius 72 vector<WeightPoint> weights_s_radius; 73 s_radius.get_weights(weights_s_radius); 75 74 76 77 78 75 // Perform the computation, with all weight points 76 double sum = 0.0; 77 double norm = 0.0; 79 78 80 81 82 79 // Loop over larger radius weight points 80 for(int i=0; i< (int)weights_l_radius.size(); i++) { 81 dp[0] = weights_l_radius[i].value; 83 82 84 85 86 83 // Loop over small radius weight points 84 for(int j=0; j< (int)weights_s_radius.size(); j++) { 85 dp[1] = weights_s_radius[j].value; 87 86 88 87 89 90 91 92 93 88 sum += weights_l_radius[i].weight *weights_s_radius[j].weight * BinaryHS(dp, q); 89 norm += weights_l_radius[i].weight *weights_s_radius[j].weight; 90 } 91 } 92 return sum/norm + background(); 94 93 } 95 94 … … 101 100 */ 102 101 double BinaryHSModel :: operator()(double qx, double qy) { 103 104 102 double q = sqrt(qx*qx + qy*qy); 103 return (*this).operator()(q); 105 104 } 106 105 … … 113 112 */ 114 113 double BinaryHSModel :: evaluate_rphi(double q, double phi) { 115 114 return (*this).operator()(q); 116 115 } 117 116 … … 121 120 */ 122 121 double BinaryHSModel :: calculate_ER() { 123 124 122 //NOT implemented yet!!! 123 return 0.0; 125 124 } 126 125 -
sansmodels/src/c_models/binaryHS_PSF11.cpp
r67424cd r82c11d3 21 21 22 22 #include <math.h> 23 #include "models.hh"24 23 #include "parameters.hh" 25 24 #include <stdio.h> … … 29 28 #include "libSphere.h" 30 29 } 30 31 class BinaryHSPSF11Model{ 32 public: 33 // Model parameters 34 Parameter l_radius; 35 Parameter s_radius; 36 Parameter vol_frac_ls; 37 Parameter vol_frac_ss; 38 Parameter ls_sld; 39 Parameter ss_sld; 40 Parameter solvent_sld; 41 Parameter background; 42 43 //Constructor 44 BinaryHSPSF11Model(); 45 46 //Operators to get I(Q) 47 double operator()(double q); 48 double operator()(double qx , double qy); 49 double calculate_ER(); 50 double evaluate_rphi(double q, double phi); 51 }; 31 52 32 53 BinaryHSPSF11Model :: BinaryHSPSF11Model() { -
sansmodels/src/c_models/c_models.cpp
r67424cd r82c11d3 68 68 void addDisperser(PyObject *module); 69 69 void addCGaussian(PyObject *module); 70 void addCLorentzian(PyObject *module);71 70 void addCLogNormal(PyObject *module); 72 71 void addCSchulz(PyObject *module); 73 72 } 73 void addCLorentzian(PyObject *module); 74 74 75 75 /** -
sansmodels/src/c_models/coreshellcylinder.cpp
r011e0e4 r82c11d3 27 27 28 28 extern "C" { 29 30 29 #include "libCylinder.h" 30 #include "libStructureFactor.h" 31 31 } 32 32 … … 63 63 double phi = pars->axis_phi * pi/180.0; 64 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 65 // Cylinder orientation 66 cyl_x = sin(theta) * cos(phi); 67 cyl_y = sin(theta) * sin(phi); 68 cyl_z = cos(theta); 69 70 // q vector 71 q_z = 0; 72 73 // Compute the angle btw vector q and the 74 // axis of the cylinder 75 cos_val = cyl_x*q_x + cyl_y*q_y + cyl_z*q_z; 76 77 // The following test should always pass 78 if (fabs(cos_val)>1.0) { 79 printf("core_shell_cylinder_analytical_2D: Unexpected error: cos(alpha)=%g\n", cos_val); 80 return 0; 81 } 82 82 83 83 alpha = acos( cos_val ); … … 85 85 // Call the IGOR library function to get the kernel 86 86 answer = CoreShellCylKernel(q, pars->radius, pars->thickness, 87 88 87 pars->core_sld,pars->shell_sld, 88 pars->solvent_sld, pars->length/2.0, alpha) / fabs(sin(alpha)); 89 89 90 90 //normalize by cylinder volume 91 91 vol=pi*(pars->radius+pars->thickness) 92 *(pars->radius+pars->thickness)93 *(pars->length+2.0*pars->thickness);92 *(pars->radius+pars->thickness) 93 *(pars->length+2.0*pars->thickness); 94 94 answer /= vol; 95 95 … … 115 115 double q; 116 116 q = sqrt(qx*qx+qy*qy); 117 117 return core_shell_cylinder_analytical_2D_scaled(pars, q, qx/q, qy/q); 118 118 } 119 119 120 120 121 121 CoreShellCylinderModel :: CoreShellCylinderModel() { 122 123 124 125 126 127 128 129 130 131 132 133 134 122 scale = Parameter(1.0); 123 radius = Parameter(20.0, true); 124 radius.set_min(0.0); 125 thickness = Parameter(10.0, true); 126 thickness.set_min(0.0); 127 length = Parameter(400.0, true); 128 length.set_min(0.0); 129 core_sld = Parameter(1.e-6); 130 shell_sld = Parameter(4.e-6); 131 solvent_sld= Parameter(1.e-6); 132 background = Parameter(0.0); 133 axis_theta = Parameter(90.0, true); 134 axis_phi = Parameter(0.0, true); 135 135 } 136 136 … … 142 142 */ 143 143 double CoreShellCylinderModel :: operator()(double q) { 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 144 double dp[8]; 145 146 dp[0] = scale(); 147 dp[1] = radius(); 148 dp[2] = thickness(); 149 dp[3] = length(); 150 dp[4] = core_sld(); 151 dp[5] = shell_sld(); 152 dp[6] = solvent_sld(); 153 dp[7] = 0.0; 154 155 // Get the dispersion points for the radius 156 vector<WeightPoint> weights_rad; 157 radius.get_weights(weights_rad); 158 159 // Get the dispersion points for the thickness 160 vector<WeightPoint> weights_thick; 161 thickness.get_weights(weights_thick); 162 163 // Get the dispersion points for the length 164 vector<WeightPoint> weights_len; 165 length.get_weights(weights_len); 166 167 // Perform the computation, with all weight points 168 double sum = 0.0; 169 double norm = 0.0; 170 double vol = 0.0; 171 172 // Loop over radius weight points 173 for(size_t i=0; i<weights_rad.size(); i++) { 174 dp[1] = weights_rad[i].value; 175 176 // Loop over length weight points 177 for(size_t j=0; j<weights_len.size(); j++) { 178 dp[3] = weights_len[j].value; 179 180 // Loop over thickness weight points 181 for(size_t k=0; k<weights_thick.size(); k++) { 182 dp[2] = weights_thick[k].value; 183 //Un-normalize by volume 184 sum += weights_rad[i].weight 185 * weights_len[j].weight 186 * weights_thick[k].weight 187 * CoreShellCylinder(dp, q) 188 * pow(weights_rad[i].value+weights_thick[k].value,2) 189 *(weights_len[j].value+2.0*weights_thick[k].value); 190 //Find average volume 191 vol += weights_rad[i].weight 192 * weights_len[j].weight 193 * weights_thick[k].weight 194 * pow(weights_rad[i].value+weights_thick[k].value,2) 195 *(weights_len[j].value+2.0*weights_thick[k].value); 196 norm += weights_rad[i].weight 197 * weights_len[j].weight 198 * weights_thick[k].weight; 199 } 200 } 201 } 202 203 if (vol != 0.0 && norm != 0.0) { 204 //Re-normalize by avg volume 205 sum = sum/(vol/norm);} 206 207 return sum/norm + background(); 208 208 } 209 209 … … 215 215 */ 216 216 double CoreShellCylinderModel :: operator()(double qx, double qy) { 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 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 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 217 CoreShellCylinderParameters dp; 218 // Fill parameter array 219 dp.scale = scale(); 220 dp.radius = radius(); 221 dp.thickness = thickness(); 222 dp.length = length(); 223 dp.core_sld = core_sld(); 224 dp.shell_sld = shell_sld(); 225 dp.solvent_sld= solvent_sld(); 226 dp.background = 0.0; 227 dp.axis_theta = axis_theta(); 228 dp.axis_phi = axis_phi(); 229 230 // Get the dispersion points for the radius 231 vector<WeightPoint> weights_rad; 232 radius.get_weights(weights_rad); 233 234 // Get the dispersion points for the thickness 235 vector<WeightPoint> weights_thick; 236 thickness.get_weights(weights_thick); 237 238 // Get the dispersion points for the length 239 vector<WeightPoint> weights_len; 240 length.get_weights(weights_len); 241 242 // Get angular averaging for theta 243 vector<WeightPoint> weights_theta; 244 axis_theta.get_weights(weights_theta); 245 246 // Get angular averaging for phi 247 vector<WeightPoint> weights_phi; 248 axis_phi.get_weights(weights_phi); 249 250 // Perform the computation, with all weight points 251 double sum = 0.0; 252 double norm = 0.0; 253 double norm_vol = 0.0; 254 double vol = 0.0; 255 double pi = 4.0*atan(1.0); 256 // Loop over radius weight points 257 for(size_t i=0; i<weights_rad.size(); i++) { 258 dp.radius = weights_rad[i].value; 259 260 261 // Loop over length weight points 262 for(size_t j=0; j<weights_len.size(); j++) { 263 dp.length = weights_len[j].value; 264 265 // Loop over thickness weight points 266 for(size_t m=0; m<weights_thick.size(); m++) { 267 dp.thickness = weights_thick[m].value; 268 269 // Average over theta distribution 270 for(size_t k=0; k<weights_theta.size(); k++) { 271 dp.axis_theta = weights_theta[k].value; 272 273 // Average over phi distribution 274 for(size_t l=0; l<weights_phi.size(); l++) { 275 dp.axis_phi = weights_phi[l].value; 276 //Un-normalize by volume 277 double _ptvalue = weights_rad[i].weight 278 * weights_len[j].weight 279 * weights_thick[m].weight 280 * weights_theta[k].weight 281 * weights_phi[l].weight 282 * core_shell_cylinder_analytical_2DXY(&dp, qx, qy) 283 * pow(weights_rad[i].value+weights_thick[m].value,2) 284 *(weights_len[j].value+2.0*weights_thick[m].value); 285 286 if (weights_theta.size()>1) { 287 _ptvalue *= fabs(sin(weights_theta[k].value*pi/180.0)); 288 } 289 sum += _ptvalue; 290 291 //Find average volume 292 vol += weights_rad[i].weight 293 * weights_len[j].weight 294 * weights_thick[m].weight 295 * pow(weights_rad[i].value+weights_thick[m].value,2) 296 *(weights_len[j].value+2.0*weights_thick[m].value); 297 //Find norm for volume 298 norm_vol += weights_rad[i].weight 299 * weights_len[j].weight 300 * weights_thick[m].weight; 301 302 norm += weights_rad[i].weight 303 * weights_len[j].weight 304 * weights_thick[m].weight 305 * weights_theta[k].weight 306 * weights_phi[l].weight; 307 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 318 if (vol != 0.0 && norm_vol != 0.0) { 319 //Re-normalize by avg volume 320 sum = sum/(vol/norm_vol);} 321 322 return sum/norm + background(); 323 323 } 324 324 … … 331 331 */ 332 332 double CoreShellCylinderModel :: evaluate_rphi(double q, double phi) { 333 334 335 333 double qx = q*cos(phi); 334 double qy = q*sin(phi); 335 return (*this).operator()(qx, qy); 336 336 } 337 337 /** … … 340 340 */ 341 341 double CoreShellCylinderModel :: calculate_ER() { 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 } 342 CoreShellCylinderParameters dp; 343 344 dp.radius = radius(); 345 dp.thickness = thickness(); 346 dp.length = length(); 347 double rad_out = 0.0; 348 349 // Perform the computation, with all weight points 350 double sum = 0.0; 351 double norm = 0.0; 352 353 // Get the dispersion points for the length 354 vector<WeightPoint> weights_length; 355 length.get_weights(weights_length); 356 357 // Get the dispersion points for the thickness 358 vector<WeightPoint> weights_thickness; 359 thickness.get_weights(weights_thickness); 360 361 // Get the dispersion points for the radius 362 vector<WeightPoint> weights_radius ; 363 radius.get_weights(weights_radius); 364 365 // Loop over major shell weight points 366 for(int i=0; i< (int)weights_length.size(); i++) { 367 dp.length = weights_length[i].value; 368 for(int j=0; j< (int)weights_thickness.size(); j++) { 369 dp.thickness = weights_thickness[j].value; 370 for(int k=0; k< (int)weights_radius.size(); k++) { 371 dp.radius = weights_radius[k].value; 372 //Note: output of "DiamCyl( )" is DIAMETER. 373 sum +=weights_length[i].weight * weights_thickness[j].weight 374 * weights_radius[k].weight*DiamCyl(dp.length+2.0*dp.thickness,dp.radius+dp.thickness)/2.0; 375 norm += weights_length[i].weight* weights_thickness[j].weight* weights_radius[k].weight; 376 } 377 } 378 } 379 if (norm != 0){ 380 //return the averaged value 381 rad_out = sum/norm;} 382 else{ 383 //return normal value 384 //Note: output of "DiamCyl()" is DIAMETER. 385 rad_out = DiamCyl(dp.length+2.0*dp.thickness,dp.radius+dp.thickness)/2.0;} 386 387 return rad_out; 388 } -
sansmodels/src/c_models/ellipsoid.cpp
r011e0e4 r82c11d3 27 27 28 28 extern "C" { 29 30 29 #include "libCylinder.h" 30 #include "libStructureFactor.h" 31 31 } 32 32 … … 60 60 double phi = pars->axis_phi * pi/180.0; 61 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 62 // Ellipsoid orientation 63 cyl_x = sin(theta) * cos(phi); 64 cyl_y = sin(theta) * sin(phi); 65 cyl_z = cos(theta); 66 67 // q vector 68 q_z = 0.0; 69 70 // Compute the angle btw vector q and the 71 // axis of the cylinder 72 cos_val = cyl_x*q_x + cyl_y*q_y + cyl_z*q_z; 73 74 // The following test should always pass 75 if (fabs(cos_val)>1.0) { 76 printf("ellipsoid_ana_2D: Unexpected error: cos(alpha)>1\n"); 77 return 0; 78 } 79 80 // Angle between rotation axis and q vector 81 81 alpha = acos( cos_val ); 82 82 … … 88 88 89 89 //normalize by cylinder volume 90 90 vol = 4.0/3.0 * acos(-1.0) * pars->radius_b * pars->radius_b * pars->radius_a; 91 91 answer *= vol; 92 92 … … 112 112 double q; 113 113 q = sqrt(qx*qx+qy*qy); 114 114 return ellipsoid_analytical_2D_scaled(pars, q, qx/q, qy/q); 115 115 } 116 116 117 117 EllipsoidModel :: EllipsoidModel() { 118 119 120 121 122 123 124 125 126 127 118 scale = Parameter(1.0); 119 radius_a = Parameter(20.0, true); 120 radius_a.set_min(0.0); 121 radius_b = Parameter(400.0, true); 122 radius_b.set_min(0.0); 123 sldEll = Parameter(4.e-6); 124 sldSolv = Parameter(1.e-6); 125 background = Parameter(0.0); 126 axis_theta = Parameter(57.325, true); 127 axis_phi = Parameter(0.0, true); 128 128 } 129 129 … … 135 135 */ 136 136 double EllipsoidModel :: operator()(double q) { 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 137 double dp[6]; 138 139 // Fill parameter array for IGOR library 140 // Add the background after averaging 141 dp[0] = scale(); 142 dp[1] = radius_a(); 143 dp[2] = radius_b(); 144 dp[3] = sldEll(); 145 dp[4] = sldSolv(); 146 dp[5] = 0.0; 147 148 // Get the dispersion points for the radius_a 149 vector<WeightPoint> weights_rad_a; 150 radius_a.get_weights(weights_rad_a); 151 152 // Get the dispersion points for the radius_b 153 vector<WeightPoint> weights_rad_b; 154 radius_b.get_weights(weights_rad_b); 155 156 // Perform the computation, with all weight points 157 double sum = 0.0; 158 double norm = 0.0; 159 double vol = 0.0; 160 161 // Loop over radius_a weight points 162 for(size_t i=0; i<weights_rad_a.size(); i++) { 163 dp[1] = weights_rad_a[i].value; 164 165 // Loop over radius_b weight points 166 for(size_t j=0; j<weights_rad_b.size(); j++) { 167 dp[2] = weights_rad_b[j].value; 168 //Un-normalize by volume 169 sum += weights_rad_a[i].weight 170 * weights_rad_b[j].weight * EllipsoidForm(dp, q) 171 * pow(weights_rad_b[j].value,2) * weights_rad_a[i].value; 172 173 //Find average volume 174 vol += weights_rad_a[i].weight 175 * weights_rad_b[j].weight 176 * pow(weights_rad_b[j].value,2) 177 * weights_rad_a[i].value; 178 norm += weights_rad_a[i].weight 179 * weights_rad_b[j].weight; 180 } 181 } 182 183 if (vol != 0.0 && norm != 0.0) { 184 //Re-normalize by avg volume 185 sum = sum/(vol/norm);} 186 187 return sum/norm + background(); 188 188 } 189 189 … … 195 195 */ 196 196 double EllipsoidModel :: operator()(double qx, double qy) { 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 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 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 197 EllipsoidParameters dp; 198 // Fill parameter array 199 dp.scale = scale(); 200 dp.radius_a = radius_a(); 201 dp.radius_b = radius_b(); 202 dp.sldEll = sldEll(); 203 dp.sldSolv = sldSolv(); 204 dp.background = 0.0; 205 dp.axis_theta = axis_theta(); 206 dp.axis_phi = axis_phi(); 207 208 // Get the dispersion points for the radius_a 209 vector<WeightPoint> weights_rad_a; 210 radius_a.get_weights(weights_rad_a); 211 212 // Get the dispersion points for the radius_b 213 vector<WeightPoint> weights_rad_b; 214 radius_b.get_weights(weights_rad_b); 215 216 // Get angular averaging for theta 217 vector<WeightPoint> weights_theta; 218 axis_theta.get_weights(weights_theta); 219 220 // Get angular averaging for phi 221 vector<WeightPoint> weights_phi; 222 axis_phi.get_weights(weights_phi); 223 224 // Perform the computation, with all weight points 225 double sum = 0.0; 226 double norm = 0.0; 227 double norm_vol = 0.0; 228 double vol = 0.0; 229 double pi = 4.0*atan(1.0); 230 // Loop over radius weight points 231 for(size_t i=0; i<weights_rad_a.size(); i++) { 232 dp.radius_a = weights_rad_a[i].value; 233 234 235 // Loop over length weight points 236 for(size_t j=0; j<weights_rad_b.size(); j++) { 237 dp.radius_b = weights_rad_b[j].value; 238 239 // Average over theta distribution 240 for(size_t k=0; k<weights_theta.size(); k++) { 241 dp.axis_theta = weights_theta[k].value; 242 243 // Average over phi distribution 244 for(size_t l=0; l<weights_phi.size(); l++) { 245 dp.axis_phi = weights_phi[l].value; 246 //Un-normalize by volume 247 double _ptvalue = weights_rad_a[i].weight 248 * weights_rad_b[j].weight 249 * weights_theta[k].weight 250 * weights_phi[l].weight 251 * ellipsoid_analytical_2DXY(&dp, qx, qy) 252 * pow(weights_rad_b[j].value,2) * weights_rad_a[i].value; 253 if (weights_theta.size()>1) { 254 _ptvalue *= fabs(sin(weights_theta[k].value*pi/180.0)); 255 } 256 sum += _ptvalue; 257 //Find average volume 258 vol += weights_rad_a[i].weight 259 * weights_rad_b[j].weight 260 * pow(weights_rad_b[j].value,2) * weights_rad_a[i].value; 261 //Find norm for volume 262 norm_vol += weights_rad_a[i].weight 263 * weights_rad_b[j].weight; 264 265 norm += weights_rad_a[i].weight 266 * weights_rad_b[j].weight 267 * weights_theta[k].weight 268 * weights_phi[l].weight; 269 270 } 271 } 272 } 273 } 274 // Averaging in theta needs an extra normalization 275 // factor to account for the sin(theta) term in the 276 // integration (see documentation). 277 if (weights_theta.size()>1) norm = norm / asin(1.0); 278 279 if (vol != 0.0 && norm_vol != 0.0) { 280 //Re-normalize by avg volume 281 sum = sum/(vol/norm_vol);} 282 283 return sum/norm + background(); 284 284 } 285 285 … … 292 292 */ 293 293 double EllipsoidModel :: evaluate_rphi(double q, double phi) { 294 295 296 294 double qx = q*cos(phi); 295 double qy = q*sin(phi); 296 return (*this).operator()(qx, qy); 297 297 } 298 298 … … 302 302 */ 303 303 double EllipsoidModel :: calculate_ER() { 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 } 304 EllipsoidParameters dp; 305 306 dp.radius_a = radius_a(); 307 dp.radius_b = radius_b(); 308 309 double rad_out = 0.0; 310 311 // Perform the computation, with all weight points 312 double sum = 0.0; 313 double norm = 0.0; 314 315 // Get the dispersion points for the major shell 316 vector<WeightPoint> weights_radius_a; 317 radius_a.get_weights(weights_radius_a); 318 319 // Get the dispersion points for the minor shell 320 vector<WeightPoint> weights_radius_b; 321 radius_b.get_weights(weights_radius_b); 322 323 // Loop over major shell weight points 324 for(int i=0; i< (int)weights_radius_b.size(); i++) { 325 dp.radius_b = weights_radius_b[i].value; 326 for(int k=0; k< (int)weights_radius_a.size(); k++) { 327 dp.radius_a = weights_radius_a[k].value; 328 sum +=weights_radius_b[i].weight 329 * weights_radius_a[k].weight*DiamEllip(dp.radius_a,dp.radius_b)/2.0; 330 norm += weights_radius_b[i].weight* weights_radius_a[k].weight; 331 } 332 } 333 if (norm != 0){ 334 //return the averaged value 335 rad_out = sum/norm;} 336 else{ 337 //return normal value 338 rad_out = DiamEllip(dp.radius_a,dp.radius_b)/2.0;} 339 340 return rad_out; 341 } -
sansmodels/src/c_models/ellipticalcylinder.cpp
r67424cd r82c11d3 18 18 * sansmodels/src/libigor 19 19 * 20 * TODO: refactor so that we pull in the old sansmodels.c_extensions21 20 */ 22 21 23 22 #include <math.h> 24 #include "models.hh"25 23 #include "parameters.hh" 26 24 #include <stdio.h> 25 #include <stdlib.h> 27 26 using namespace std; 27 #include "elliptical_cylinder.h" 28 28 29 29 extern "C" { 30 #include "libCylinder.h" 31 #include "libStructureFactor.h" 32 #include "elliptical_cylinder.h" 30 #include "libCylinder.h" 31 #include "libStructureFactor.h" 32 } 33 34 typedef struct { 35 double scale; 36 double r_minor; 37 double r_ratio; 38 double length; 39 double sldCyl; 40 double sldSolv; 41 double background; 42 double cyl_theta; 43 double cyl_phi; 44 double cyl_psi; 45 } EllipticalCylinderParameters; 46 47 48 static double elliptical_cylinder_kernel(EllipticalCylinderParameters *pars, double q, double alpha, double nu) { 49 double qr; 50 double qL; 51 double Be,Si; 52 double r_major; 53 double kernel; 54 55 r_major = pars->r_ratio * pars->r_minor; 56 57 qr = q*sin(alpha)*sqrt( r_major*r_major*sin(nu)*sin(nu) + pars->r_minor*pars->r_minor*cos(nu)*cos(nu) ); 58 qL = q*pars->length*cos(alpha)/2.0; 59 60 if (qr==0){ 61 Be = 0.5; 62 }else{ 63 Be = NR_BessJ1(qr)/qr; 64 } 65 if (qL==0){ 66 Si = 1.0; 67 }else{ 68 Si = sin(qL)/qL; 69 } 70 71 72 kernel = 2.0*Be * Si; 73 return kernel*kernel; 74 } 75 76 /** 77 * Function to evaluate 2D scattering function 78 * @param pars: parameters of the cylinder 79 * @param q: q-value 80 * @param q_x: q_x / q 81 * @param q_y: q_y / q 82 * @return: function value 83 */ 84 static double elliptical_cylinder_analytical_2D_scaled(EllipticalCylinderParameters *pars, double q, double q_x, double q_y) { 85 double cyl_x, cyl_y, cyl_z; 86 double ell_x, ell_y; 87 double q_z; 88 double alpha, vol, cos_val; 89 double nu, cos_nu; 90 double answer; 91 //convert angle degree to radian 92 double pi = 4.0*atan(1.0); 93 double theta = pars->cyl_theta * pi/180.0; 94 double phi = pars->cyl_phi * pi/180.0; 95 double psi = pars->cyl_psi * pi/180.0; 96 97 //Cylinder orientation 98 cyl_x = sin(theta) * cos(phi); 99 cyl_y = sin(theta) * sin(phi); 100 cyl_z = cos(theta); 101 102 // q vector 103 q_z = 0; 104 105 // Compute the angle btw vector q and the 106 // axis of the cylinder 107 cos_val = cyl_x*q_x + cyl_y*q_y + cyl_z*q_z; 108 109 // The following test should always pass 110 if (fabs(cos_val)>1.0) { 111 printf("cyl_ana_2D: Unexpected error: cos(alpha)>1\n"); 112 return 0; 113 } 114 115 // Note: cos(alpha) = 0 and 1 will get an 116 // undefined value from CylKernel 117 alpha = acos( cos_val ); 118 119 //ellipse orientation: 120 // the elliptical corss section was transformed and projected 121 // into the detector plane already through sin(alpha)and furthermore psi remains as same 122 // on the detector plane. 123 // So, all we need is to calculate the angle (nu) of the minor axis of the ellipse wrt 124 // the wave vector q. 125 126 //x- y- component on the detector plane. 127 ell_x = cos(psi); 128 ell_y = sin(psi); 129 130 // calculate the axis of the ellipse wrt q-coord. 131 cos_nu = ell_x*q_x + ell_y*q_y; 132 nu = acos(cos_nu); 133 134 // The following test should always pass 135 if (fabs(cos_nu)>1.0) { 136 printf("cyl_ana_2D: Unexpected error: cos(nu)>1\n"); 137 return 0; 138 } 139 140 answer = elliptical_cylinder_kernel(pars, q, alpha,nu); 141 142 // Multiply by contrast^2 143 answer *= (pars->sldCyl - pars->sldSolv) * (pars->sldCyl - pars->sldSolv); 144 145 //normalize by cylinder volume 146 //NOTE that for this (Fournet) definition of the integral, one must MULTIPLY by Vcyl 147 vol = acos(-1.0) * pars->r_minor * pars->r_minor * pars->r_ratio * pars->length; 148 answer *= vol; 149 150 //convert to [cm-1] 151 answer *= 1.0e8; 152 153 //Scale 154 answer *= pars->scale; 155 156 // add in the background 157 answer += pars->background; 158 159 return answer; 160 } 161 162 163 /** 164 * Function to evaluate 2D scattering function 165 * @param pars: parameters of the cylinder 166 * @param q: q-value 167 * @return: function value 168 */ 169 static double elliptical_cylinder_analytical_2DXY(EllipticalCylinderParameters *pars, double qx, double qy) { 170 double q; 171 q = sqrt(qx*qx+qy*qy); 172 return elliptical_cylinder_analytical_2D_scaled(pars, q, qx/q, qy/q); 33 173 } 34 174 35 175 EllipticalCylinderModel :: EllipticalCylinderModel() { 36 37 38 39 40 41 42 43 44 45 46 47 48 176 scale = Parameter(1.0); 177 r_minor = Parameter(20.0, true); 178 r_minor.set_min(0.0); 179 r_ratio = Parameter(1.5, true); 180 r_ratio.set_min(0.0); 181 length = Parameter(400.0, true); 182 length.set_min(0.0); 183 sldCyl = Parameter(4.e-6); 184 sldSolv = Parameter(1.e-6); 185 background = Parameter(0.0); 186 cyl_theta = Parameter(57.325, true); 187 cyl_phi = Parameter(0.0, true); 188 cyl_psi = Parameter(0.0, true); 49 189 } 50 190 … … 56 196 */ 57 197 double EllipticalCylinderModel :: operator()(double q) { 58 59 60 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 198 double dp[7]; 199 200 dp[0] = scale(); 201 dp[1] = r_minor(); 202 dp[2] = r_ratio(); 203 dp[3] = length(); 204 dp[4] = sldCyl(); 205 dp[5] = sldSolv(); 206 dp[6] = 0.0; 207 208 // Get the dispersion points for the r_minor 209 vector<WeightPoint> weights_rad; 210 r_minor.get_weights(weights_rad); 211 212 // Get the dispersion points for the r_ratio 213 vector<WeightPoint> weights_rat; 214 r_ratio.get_weights(weights_rat); 215 216 // Get the dispersion points for the length 217 vector<WeightPoint> weights_len; 218 length.get_weights(weights_len); 219 220 // Perform the computation, with all weight points 221 double sum = 0.0; 222 double norm = 0.0; 223 double vol = 0.0; 224 225 // Loop over r_minor weight points 226 for(size_t i=0; i<weights_rad.size(); i++) { 227 dp[1] = weights_rad[i].value; 228 229 // Loop over r_ratio weight points 230 for(size_t j=0; j<weights_rat.size(); j++) { 231 dp[2] = weights_rat[j].value; 232 233 // Loop over length weight points 234 for(size_t k=0; k<weights_len.size(); k++) { 235 dp[3] = weights_len[k].value; 236 //Un-normalize by volume 237 sum += weights_rad[i].weight 238 * weights_len[k].weight 239 * weights_rat[j].weight 240 * EllipCyl20(dp, q) 241 * pow(weights_rad[i].value,2) * weights_rat[j].value 242 * weights_len[k].value; 243 //Find average volume 244 vol += weights_rad[i].weight 245 * weights_len[k].weight 246 * weights_rat[j].weight 247 * pow(weights_rad[i].value,2) * weights_rat[j].value 248 * weights_len[k].value; 249 norm += weights_rad[i].weight 250 * weights_len[k].weight 251 * weights_rat[j].weight; 252 } 253 } 254 } 255 256 if (vol != 0.0 && norm != 0.0) { 257 //Re-normalize by avg volume 258 sum = sum/(vol/norm);} 259 260 return sum/norm + background(); 121 261 } 122 262 … … 128 268 */ 129 269 double EllipticalCylinderModel :: operator()(double qx, double qy) { 130 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 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 270 EllipticalCylinderParameters dp; 271 // Fill parameter array 272 dp.scale = scale(); 273 dp.r_minor = r_minor(); 274 dp.r_ratio = r_ratio(); 275 dp.length = length(); 276 dp.sldCyl = sldCyl(); 277 dp.sldSolv = sldSolv(); 278 dp.background = 0.0; 279 dp.cyl_theta = cyl_theta(); 280 dp.cyl_phi = cyl_phi(); 281 dp.cyl_psi = cyl_psi(); 282 283 // Get the dispersion points for the r_minor 284 vector<WeightPoint> weights_rad; 285 r_minor.get_weights(weights_rad); 286 287 // Get the dispersion points for the r_ratio 288 vector<WeightPoint> weights_rat; 289 r_ratio.get_weights(weights_rat); 290 291 // Get the dispersion points for the length 292 vector<WeightPoint> weights_len; 293 length.get_weights(weights_len); 294 295 // Get angular averaging for theta 296 vector<WeightPoint> weights_theta; 297 cyl_theta.get_weights(weights_theta); 298 299 // Get angular averaging for phi 300 vector<WeightPoint> weights_phi; 301 cyl_phi.get_weights(weights_phi); 302 303 // Get angular averaging for psi 304 vector<WeightPoint> weights_psi; 305 cyl_psi.get_weights(weights_psi); 306 307 // Perform the computation, with all weight points 308 double sum = 0.0; 309 double norm = 0.0; 310 double norm_vol = 0.0; 311 double vol = 0.0; 312 double pi = 4.0*atan(1.0); 313 // Loop over minor radius weight points 314 for(size_t i=0; i<weights_rad.size(); i++) { 315 dp.r_minor = weights_rad[i].value; 316 317 318 // Loop over length weight points 319 for(size_t j=0; j<weights_len.size(); j++) { 320 dp.length = weights_len[j].value; 321 322 // Loop over r_ration weight points 323 for(size_t m=0; m<weights_rat.size(); m++) { 324 dp.r_ratio = weights_rat[m].value; 325 326 // Average over theta distribution 327 for(size_t k=0; k<weights_theta.size(); k++) { 328 dp.cyl_theta = weights_theta[k].value; 329 330 // Average over phi distribution 331 for(size_t l=0; l<weights_phi.size(); l++) { 332 dp.cyl_phi = weights_phi[l].value; 333 334 // Average over phi distribution 335 for(size_t o=0; o<weights_psi.size(); o++) { 336 dp.cyl_psi = weights_psi[o].value; 337 //Un-normalize by volume 338 double _ptvalue = weights_rad[i].weight 339 * weights_len[j].weight 340 * weights_rat[m].weight 341 * weights_theta[k].weight 342 * weights_phi[l].weight 343 * weights_psi[o].weight 344 * elliptical_cylinder_analytical_2DXY(&dp, qx, qy) 345 * pow(weights_rad[i].value,2) 346 * weights_len[j].value 347 * weights_rat[m].value; 348 if (weights_theta.size()>1) { 349 _ptvalue *= fabs(sin(weights_theta[k].value*pi/180.0)); 350 } 351 sum += _ptvalue; 352 //Find average volume 353 vol += weights_rad[i].weight 354 * weights_len[j].weight 355 * weights_rat[m].weight 356 * pow(weights_rad[i].value,2) 357 * weights_len[j].value 358 * weights_rat[m].value; 359 //Find norm for volume 360 norm_vol += weights_rad[i].weight 361 * weights_len[j].weight 362 * weights_rat[m].weight; 363 364 norm += weights_rad[i].weight 365 * weights_len[j].weight 366 * weights_rat[m].weight 367 * weights_theta[k].weight 368 * weights_phi[l].weight 369 * weights_psi[o].weight; 370 371 } 372 } 373 } 374 } 375 } 376 } 377 // Averaging in theta needs an extra normalization 378 // factor to account for the sin(theta) term in the 379 // integration (see documentation). 380 if (weights_theta.size()>1) norm = norm / asin(1.0); 381 382 if (vol != 0.0 && norm_vol != 0.0) { 383 //Re-normalize by avg volume 384 sum = sum/(vol/norm_vol);} 385 386 return sum/norm + background(); 247 387 248 388 } … … 256 396 */ 257 397 double EllipticalCylinderModel :: evaluate_rphi(double q, double phi) { 258 259 260 398 double qx = q*cos(phi); 399 double qy = q*sin(phi); 400 return (*this).operator()(qx, qy); 261 401 } 262 402 /** … … 265 405 */ 266 406 double EllipticalCylinderModel :: calculate_ER() { 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 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 } 407 EllipticalCylinderParameters dp; 408 dp.r_minor = r_minor(); 409 dp.r_ratio = r_ratio(); 410 dp.length = length(); 411 double rad_out = 0.0; 412 double suf_rad = sqrt(dp.r_minor*dp.r_minor*dp.r_ratio); 413 414 // Perform the computation, with all weight points 415 double sum = 0.0; 416 double norm = 0.0; 417 418 // Get the dispersion points for the r_minor 419 vector<WeightPoint> weights_rad; 420 r_minor.get_weights(weights_rad); 421 422 // Get the dispersion points for the r_ratio 423 vector<WeightPoint> weights_rat; 424 r_ratio.get_weights(weights_rat); 425 426 // Get the dispersion points for the length 427 vector<WeightPoint> weights_len; 428 length.get_weights(weights_len); 429 430 // Loop over minor radius weight points 431 for(size_t i=0; i<weights_rad.size(); i++) { 432 dp.r_minor = weights_rad[i].value; 433 434 // Loop over length weight points 435 for(size_t j=0; j<weights_len.size(); j++) { 436 dp.length = weights_len[j].value; 437 438 // Loop over r_ration weight points 439 for(size_t m=0; m<weights_rat.size(); m++) { 440 dp.r_ratio = weights_rat[m].value; 441 //Calculate surface averaged radius 442 suf_rad = sqrt(dp.r_minor * dp.r_minor * dp.r_ratio); 443 444 //Note: output of "DiamCyl(dp.length,dp.radius)" is DIAMETER. 445 sum +=weights_rad[i].weight *weights_len[j].weight 446 * weights_rat[m].weight*DiamCyl(dp.length, suf_rad)/2.0; 447 norm += weights_rad[i].weight *weights_len[j].weight* weights_rat[m].weight; 448 } 449 } 450 } 451 if (norm != 0){ 452 //return the averaged value 453 rad_out = sum/norm;} 454 else{ 455 //return normal value 456 //Note: output of "DiamCyl(dp.length,dp.radius)" is DIAMETER. 457 rad_out = DiamCyl(dp.length, suf_rad)/2.0;} 458 459 return rad_out; 460 } -
sansmodels/src/c_models/flexcyl_ellipX.cpp
r67424cd r82c11d3 21 21 22 22 #include <math.h> 23 #include "models.hh"24 23 #include "parameters.hh" 25 24 #include <stdio.h> 26 25 using namespace std; 26 #include "flexcyl_ellipX.h" 27 27 28 28 extern "C" { 29 #include "libCylinder.h" 30 #include "libStructureFactor.h" 31 #include "flexcyl_ellipX.h" 32 } 29 #include "libCylinder.h" 30 #include "libStructureFactor.h" 31 } 32 33 typedef struct { 34 double scale; 35 double length; 36 double kuhn_length; 37 double radius; 38 double axis_ratio; 39 double sldCyl; 40 double sldSolv; 41 double background; 42 } FlexCylEXParameters; 33 43 34 44 FlexCylEllipXModel :: FlexCylEllipXModel() { 35 36 37 38 39 40 41 42 43 44 45 46 45 scale = Parameter(1.0); 46 length = Parameter(1000.0, true); 47 length.set_min(0.0); 48 kuhn_length = Parameter(100.0, true); 49 kuhn_length.set_min(0.0); 50 radius = Parameter(20.0, true); 51 radius.set_min(0.0); 52 axis_ratio = Parameter(1.5); 53 axis_ratio.set_min(0.0); 54 sldCyl = Parameter(1.0e-6); 55 sldSolv = Parameter(6.3e-6); 56 background = Parameter(0.0001); 47 57 } 48 58 … … 54 64 */ 55 65 double FlexCylEllipXModel :: operator()(double q) { 56 57 58 59 60 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 122 123 66 double dp[8]; 67 68 // Fill parameter array for IGOR library 69 // Add the background after averaging 70 dp[0] = scale(); 71 dp[1] = length(); 72 dp[2] = kuhn_length(); 73 dp[3] = radius(); 74 dp[4] = axis_ratio(); 75 dp[5] = sldCyl(); 76 dp[6] = sldSolv(); 77 dp[7] = 0.0; 78 79 // Get the dispersion points for the length 80 vector<WeightPoint> weights_len; 81 length.get_weights(weights_len); 82 83 // Get the dispersion points for the kuhn_length 84 vector<WeightPoint> weights_kuhn; 85 kuhn_length.get_weights(weights_kuhn); 86 87 // Get the dispersion points for the radius 88 vector<WeightPoint> weights_rad; 89 radius.get_weights(weights_rad); 90 91 // Get the dispersion points for the axis_ratio 92 vector<WeightPoint> weights_ratio; 93 axis_ratio.get_weights(weights_ratio); 94 95 // Perform the computation, with all weight points 96 double sum = 0.0; 97 double norm = 0.0; 98 double vol = 0.0; 99 100 // Loop over length weight points 101 for(int i=0; i< (int)weights_len.size(); i++) { 102 dp[1] = weights_len[i].value; 103 104 // Loop over kuhn_length weight points 105 for(int j=0; j< (int)weights_kuhn.size(); j++) { 106 dp[2] = weights_kuhn[j].value; 107 108 // Loop over radius weight points 109 for(int k=0; k< (int)weights_rad.size(); k++) { 110 dp[3] = weights_rad[k].value; 111 // Loop over axis_ratio weight points 112 for(int l=0; l< (int)weights_ratio.size(); l++) { 113 dp[4] = weights_ratio[l].value; 114 115 //Un-normalize by volume 116 sum += weights_len[i].weight * weights_kuhn[j].weight*weights_rad[k].weight 117 * weights_ratio[l].weight * FlexCyl_Ellip(dp, q) 118 * (pow(weights_rad[k].value,2.0) * weights_ratio[l].value * weights_len[i].value); 119 //Find weighted volume 120 vol += weights_rad[k].weight * weights_kuhn[j].weight 121 * weights_len[i].weight * weights_ratio[l].weight 122 *pow(weights_rad[k].value,2.0)* weights_ratio[l].weight*weights_len[i].value; 123 norm += weights_len[i].weight * weights_kuhn[j].weight 124 *weights_rad[k].weight* weights_ratio[l].weight; 125 } 126 } 127 } 128 } 129 if (vol != 0.0 && norm != 0.0) { 130 //Re-normalize by avg volume 131 sum = sum/(vol/norm);} 132 133 return sum/norm + background(); 124 134 } 125 135 … … 131 141 */ 132 142 double FlexCylEllipXModel :: operator()(double qx, double qy) { 133 134 143 double q = sqrt(qx*qx + qy*qy); 144 return (*this).operator()(q); 135 145 } 136 146 … … 143 153 */ 144 154 double FlexCylEllipXModel :: evaluate_rphi(double q, double phi) { 145 146 147 155 //double qx = q*cos(phi); 156 //double qy = q*sin(phi); 157 return (*this).operator()(q); 148 158 } 149 159 /** … … 152 162 */ 153 163 double FlexCylEllipXModel :: calculate_ER() { 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 } 164 FlexCylEXParameters dp; 165 166 dp.radius = radius(); 167 dp.length = length(); 168 dp.axis_ratio = axis_ratio(); 169 170 double rad_out = 0.0; 171 double suf_rad = sqrt(dp.radius*dp.radius*dp.axis_ratio ); 172 // Perform the computation, with all weight points 173 double sum = 0.0; 174 double norm = 0.0; 175 176 // Get the dispersion points for the total length 177 vector<WeightPoint> weights_length; 178 length.get_weights(weights_length); 179 180 // Get the dispersion points for minor radius 181 vector<WeightPoint> weights_radius ; 182 radius.get_weights(weights_radius); 183 184 // Get the dispersion points for axis ratio = major_radius/minor_radius 185 vector<WeightPoint> weights_ratio ; 186 axis_ratio.get_weights(weights_ratio); 187 188 // Loop over major shell weight points 189 for(int i=0; i< (int)weights_length.size(); i++) { 190 dp.length = weights_length[i].value; 191 for(int k=0; k< (int)weights_radius.size(); k++) { 192 dp.radius = weights_radius[k].value; 193 // Loop over axis_ratio weight points 194 for(int l=0; l< (int)weights_ratio.size(); l++) { 195 dp.axis_ratio = weights_ratio[l].value; 196 suf_rad = sqrt(dp.radius * dp.radius * dp.axis_ratio); 197 //Note: output of "DiamCyl(dp.length,dp.radius)" is DIAMETER. 198 sum +=weights_length[i].weight * weights_radius[k].weight 199 * weights_ratio[l].weight *DiamCyl(dp.length,suf_rad)/2.0; 200 norm += weights_length[i].weight* weights_radius[k].weight* weights_ratio[l].weight; 201 } 202 } 203 } 204 if (norm != 0){ 205 //return the averaged value 206 rad_out = sum/norm;} 207 else{ 208 //return normal value 209 //Note: output of "DiamCyl(dp.length,dp.radius)" is DIAMETER. 210 rad_out = DiamCyl(dp.length,suf_rad)/2.0;} 211 212 return rad_out; 213 } -
sansmodels/src/c_models/flexiblecylinder.cpp
r67424cd r82c11d3 18 18 * sansmodels/src/libigor 19 19 * 20 * TODO: refactor so that we pull in the old sansmodels.c_extensions21 20 * TODO: add 2d 22 21 */ 23 22 24 23 #include <math.h> 25 #include "models.hh"26 24 #include "parameters.hh" 27 25 #include <stdio.h> 28 26 using namespace std; 27 #include "flexible_cylinder.h" 29 28 30 29 extern "C" { 31 30 #include "libCylinder.h" 32 31 #include "libStructureFactor.h" 33 #include "flexible_cylinder.h"34 32 } 33 34 typedef struct { 35 double scale; 36 double length; 37 double kuhn_length; 38 double radius; 39 double sldCyl; 40 double sldSolv; 41 double background; 42 } FlexibleCylinderParameters; 35 43 36 44 FlexibleCylinderModel :: FlexibleCylinderModel() { -
sansmodels/src/c_models/fractal.cpp
r67424cd r82c11d3 21 21 22 22 #include <math.h> 23 #include "models.hh"24 23 #include "parameters.hh" 25 24 #include <stdio.h> 26 25 using namespace std; 26 #include "fractal.h" 27 27 28 28 extern "C" { 29 #include "libTwoPhase.h" 30 #include "fractal.h" 29 #include "libTwoPhase.h" 31 30 } 32 31 33 32 FractalModel :: FractalModel() { 34 35 36 37 38 39 40 41 33 scale = Parameter(1.0); 34 radius = Parameter(5.0, true); 35 radius.set_min(0.0); 36 fractal_dim = Parameter(2.0); 37 cor_length = Parameter(100.0); 38 sldBlock = Parameter(2.0e-6); 39 sldSolv= Parameter(6.35e-6); 40 background = Parameter(0.0); 42 41 } 43 42 … … 49 48 */ 50 49 double FractalModel :: operator()(double q) { 51 50 double dp[7]; 52 51 53 54 55 56 57 58 59 60 61 52 // Fill parameter array for IGOR library 53 // Add the background after averaging 54 dp[0] = scale(); 55 dp[1] = radius(); 56 dp[2] = fractal_dim(); 57 dp[3] = cor_length(); 58 dp[4] = sldBlock(); 59 dp[5] = sldSolv(); 60 dp[6] = 0.0; 62 61 63 64 65 62 // Get the dispersion points for the radius 63 vector<WeightPoint> weights_rad; 64 radius.get_weights(weights_rad); 66 65 67 68 69 70 66 // Perform the computation, with all weight points 67 double sum = 0.0; 68 double norm = 0.0; 69 double vol = 0.0; 71 70 72 73 74 71 // Loop over radius weight points 72 for(size_t i=0; i<weights_rad.size(); i++) { 73 dp[1] = weights_rad[i].value; 75 74 76 77 78 79 80 81 75 //Un-normalize Fractal by volume 76 sum += weights_rad[i].weight 77 * Fractal(dp, fabs(q)) * pow(weights_rad[i].value,3); 78 //Find average volume 79 vol += weights_rad[i].weight 80 * pow(weights_rad[i].value,3); 82 81 83 84 82 norm += weights_rad[i].weight; 83 } 85 84 86 87 88 89 85 if (vol != 0.0 && norm != 0.0) { 86 //Re-normalize by avg volume 87 sum = sum/(vol/norm);} 88 return sum/norm + background(); 90 89 } 91 90 … … 97 96 */ 98 97 double FractalModel :: operator()(double qx, double qy) { 99 100 98 double q = sqrt(qx*qx + qy*qy); 99 return (*this).operator()(q); 101 100 } 102 101 … … 109 108 */ 110 109 double FractalModel :: evaluate_rphi(double q, double phi) { 111 110 return (*this).operator()(q); 112 111 } 113 112 … … 117 116 */ 118 117 double FractalModel :: calculate_ER() { 119 120 118 //NOT implemented yet!!! 'cause None shape Model 119 return 0.0; 121 120 } -
sansmodels/src/c_models/hollowcylinder.cpp
r67424cd r82c11d3 18 18 * sansmodels/src/libigor 19 19 * 20 * TODO: refactor so that we pull in the old sansmodels.c_extensions21 20 */ 22 21 23 22 #include <math.h> 24 #include "models.hh"25 23 #include "parameters.hh" 26 24 #include <stdio.h> 27 25 using namespace std; 26 #include "hollow_cylinder.h" 28 27 29 28 extern "C" { 30 #include "libCylinder.h" 31 #include "libStructureFactor.h" 32 #include "hollow_cylinder.h" 29 #include "libCylinder.h" 30 #include "libStructureFactor.h" 31 } 32 33 typedef struct { 34 double scale; 35 double core_radius; 36 double radius; 37 double length; 38 double sldCyl; 39 double sldSolv; 40 double background; 41 double axis_theta; 42 double axis_phi; 43 } HollowCylinderParameters; 44 45 /** 46 * Function to evaluate 2D scattering function 47 * @param pars: parameters of the hollow cylinder 48 * @param q: q-value 49 * @param q_x: q_x / q 50 * @param q_y: q_y / q 51 * @return: function value 52 */ 53 static double hollow_cylinder_analytical_2D_scaled(HollowCylinderParameters *pars, double q, double q_x, double q_y) { 54 double cyl_x, cyl_y, cyl_z; 55 double q_z; 56 double alpha,vol, cos_val; 57 double answer; 58 //convert angle degree to radian 59 double pi = 4.0*atan(1.0); 60 double theta = pars->axis_theta * pi/180.0; 61 double phi = pars->axis_phi * pi/180.0; 62 63 // Cylinder orientation 64 cyl_x = sin(theta) * cos(phi); 65 cyl_y = sin(theta) * sin(phi); 66 cyl_z = cos(theta); 67 68 // q vector 69 q_z = 0; 70 71 // Compute the angle btw vector q and the 72 // axis of the cylinder 73 cos_val = cyl_x*q_x + cyl_y*q_y + cyl_z*q_z; 74 75 // The following test should always pass 76 if (fabs(cos_val)>1.0) { 77 printf("core_shell_cylinder_analytical_2D: Unexpected error: cos(alpha)=%g\n", cos_val); 78 return 0; 79 } 80 81 alpha = acos( cos_val ); 82 83 // Call the IGOR library function to get the kernel 84 answer = HolCylKernel(q, pars->core_radius, pars->radius, pars->length, cos_val); 85 86 // Multiply by contrast^2 87 answer *= (pars->sldCyl - pars->sldSolv)*(pars->sldCyl - pars->sldSolv); 88 89 //normalize by cylinder volume 90 vol=pi*((pars->radius*pars->radius)-(pars->core_radius *pars->core_radius)) 91 *(pars->length); 92 answer *= vol; 93 94 //convert to [cm-1] 95 answer *= 1.0e8; 96 97 //Scale 98 answer *= pars->scale; 99 100 // add in the background 101 answer += pars->background; 102 103 return answer; 104 } 105 106 107 108 /** 109 * Function to evaluate 2D scattering function 110 * @param pars: parameters of the Hollow cylinder 111 * @param q: q-value 112 * @return: function value 113 */ 114 static double hollow_cylinder_analytical_2DXY(HollowCylinderParameters *pars, double qx, double qy) { 115 double q; 116 q = sqrt(qx*qx+qy*qy); 117 return hollow_cylinder_analytical_2D_scaled(pars, q, qx/q, qy/q); 33 118 } 34 119 35 120 HollowCylinderModel :: HollowCylinderModel() { 36 37 38 39 40 41 42 43 44 45 46 47 121 scale = Parameter(1.0); 122 core_radius = Parameter(20.0, true); 123 core_radius.set_min(0.0); 124 radius = Parameter(30.0, true); 125 radius.set_min(0.0); 126 length = Parameter(400.0, true); 127 length.set_min(0.0); 128 sldCyl = Parameter(6.3e-6); 129 sldSolv = Parameter(1.0e-6); 130 background = Parameter(0.0); 131 axis_theta = Parameter(0.0, true); 132 axis_phi = Parameter(0.0, true); 48 133 } 49 134 … … 55 140 */ 56 141 double HollowCylinderModel :: operator()(double q) { 57 58 59 60 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 142 double dp[7]; 143 144 dp[0] = scale(); 145 dp[1] = core_radius(); 146 dp[2] = radius(); 147 dp[3] = length(); 148 dp[4] = sldCyl(); 149 dp[5] = sldSolv(); 150 dp[6] = 0.0; 151 152 // Get the dispersion points for the core radius 153 vector<WeightPoint> weights_core_radius; 154 core_radius.get_weights(weights_core_radius); 155 156 // Get the dispersion points for the shell radius 157 vector<WeightPoint> weights_radius; 158 radius.get_weights(weights_radius); 159 160 // Get the dispersion points for the length 161 vector<WeightPoint> weights_length; 162 length.get_weights(weights_length); 163 164 // Perform the computation, with all weight points 165 double sum = 0.0; 166 double norm = 0.0; 167 double vol = 0.0; 168 169 // Loop over core radius weight points 170 for(int i=0; i< (int)weights_core_radius.size(); i++) { 171 dp[1] = weights_core_radius[i].value; 172 173 // Loop over length weight points 174 for(int j=0; j< (int)weights_length.size(); j++) { 175 dp[3] = weights_length[j].value; 176 177 // Loop over shell radius weight points 178 for(int k=0; k< (int)weights_radius.size(); k++) { 179 dp[2] = weights_radius[k].value; 180 //Un-normalize by volume 181 sum += weights_core_radius[i].weight 182 * weights_length[j].weight 183 * weights_radius[k].weight 184 * HollowCylinder(dp, q) 185 * (pow(weights_radius[k].value,2)-pow(weights_core_radius[i].value,2)) 186 * weights_length[j].value; 187 //Find average volume 188 vol += weights_core_radius[i].weight 189 * weights_length[j].weight 190 * weights_radius[k].weight 191 * (pow(weights_radius[k].value,2)-pow(weights_core_radius[i].value,2)) 192 * weights_length[j].value; 193 194 norm += weights_core_radius[i].weight 195 * weights_length[j].weight 196 * weights_radius[k].weight; 197 } 198 } 199 } 200 if (vol != 0.0 && norm != 0.0) { 201 //Re-normalize by avg volume 202 sum = sum/(vol/norm);} 203 204 return sum/norm + background(); 120 205 } 121 206 … … 127 212 */ 128 213 double HollowCylinderModel :: operator()(double qx, double qy) { 129 130 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 229 214 HollowCylinderParameters dp; 215 // Fill parameter array 216 dp.scale = scale(); 217 dp.core_radius = core_radius(); 218 dp.radius = radius(); 219 dp.length = length(); 220 dp.sldCyl = sldCyl(); 221 dp.sldSolv = sldSolv(); 222 dp.background = 0.0; 223 dp.axis_theta = axis_theta(); 224 dp.axis_phi = axis_phi(); 225 226 // Get the dispersion points for the core radius 227 vector<WeightPoint> weights_core_radius; 228 core_radius.get_weights(weights_core_radius); 229 230 // Get the dispersion points for the shell radius 231 vector<WeightPoint> weights_radius; 232 radius.get_weights(weights_radius); 233 234 // Get the dispersion points for the length 235 vector<WeightPoint> weights_length; 236 length.get_weights(weights_length); 237 238 // Get angular averaging for theta 239 vector<WeightPoint> weights_theta; 240 axis_theta.get_weights(weights_theta); 241 242 // Get angular averaging for phi 243 vector<WeightPoint> weights_phi; 244 axis_phi.get_weights(weights_phi); 245 246 // Perform the computation, with all weight points 247 double sum = 0.0; 248 double norm = 0.0; 249 double norm_vol = 0.0; 250 double vol = 0.0; 251 double pi = 4.0*atan(1.0); 252 // Loop over core radius weight points 253 for(int i=0; i<(int)weights_core_radius.size(); i++) { 254 dp.core_radius = weights_core_radius[i].value; 255 256 257 // Loop over length weight points 258 for(int j=0; j<(int)weights_length.size(); j++) { 259 dp.length = weights_length[j].value; 260 261 // Loop over shell radius weight points 262 for(int m=0; m< (int)weights_radius.size(); m++) { 263 dp.radius = weights_radius[m].value; 264 265 // Average over theta distribution 266 for(int k=0; k< (int)weights_theta.size(); k++) { 267 dp.axis_theta = weights_theta[k].value; 268 269 // Average over phi distribution 270 for(int l=0; l< (int)weights_phi.size(); l++) { 271 dp.axis_phi = weights_phi[l].value; 272 //Un-normalize by volume 273 double _ptvalue = weights_core_radius[i].weight 274 * weights_length[j].weight 275 * weights_radius[m].weight 276 * weights_theta[k].weight 277 * weights_phi[l].weight 278 * hollow_cylinder_analytical_2DXY(&dp, qx, qy) 279 / ((pow(weights_radius[m].value,2)-pow(weights_core_radius[i].value,2)) 280 * weights_length[j].value); 281 if (weights_theta.size()>1) { 282 _ptvalue *= fabs(sin(weights_theta[k].value * pi/180.0)); 283 } 284 sum += _ptvalue; 285 //Find average volume 286 vol += weights_core_radius[i].weight 287 * weights_length[j].weight 288 * weights_radius[m].weight 289 * (pow(weights_radius[m].value,2)-pow(weights_core_radius[i].value,2)) 290 * weights_length[j].value; 291 //Find norm for volume 292 norm_vol += weights_core_radius[i].weight 293 * weights_length[j].weight 294 * weights_radius[m].weight; 295 296 norm += weights_core_radius[i].weight 297 * weights_length[j].weight 298 * weights_radius[m].weight 299 * weights_theta[k].weight 300 * weights_phi[l].weight; 301 302 } 303 } 304 } 305 } 306 } 307 // Averaging in theta needs an extra normalization 308 // factor to account for the sin(theta) term in the 309 // integration (see documentation). 310 if (weights_theta.size()>1) norm = norm/asin(1.0); 311 if (vol != 0.0 || norm_vol != 0.0) { 312 //Re-normalize by avg volume 313 sum = sum*(vol/norm_vol);} 314 return sum/norm + background(); 230 315 } 231 316 … … 238 323 */ 239 324 double HollowCylinderModel :: evaluate_rphi(double q, double phi) { 240 241 242 325 double qx = q*cos(phi); 326 double qy = q*sin(phi); 327 return (*this).operator()(qx, qy); 243 328 } 244 329 /** … … 247 332 */ 248 333 double HollowCylinderModel :: calculate_ER() { 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 } 334 HollowCylinderParameters dp; 335 336 dp.radius = radius(); 337 dp.length = length(); 338 339 double rad_out = 0.0; 340 341 // Perform the computation, with all weight points 342 double sum = 0.0; 343 double norm = 0.0; 344 345 // Get the dispersion points for the major shell 346 vector<WeightPoint> weights_length; 347 length.get_weights(weights_length); 348 349 // Get the dispersion points for the minor shell 350 vector<WeightPoint> weights_radius ; 351 radius.get_weights(weights_radius); 352 353 // Loop over major shell weight points 354 for(int i=0; i< (int)weights_length.size(); i++) { 355 dp.length = weights_length[i].value; 356 for(int k=0; k< (int)weights_radius.size(); k++) { 357 dp.radius = weights_radius[k].value; 358 //Note: output of "DiamCyl(dp.length,dp.radius)" is DIAMETER. 359 sum +=weights_length[i].weight 360 * weights_radius[k].weight*DiamCyl(dp.length,dp.radius)/2.0; 361 norm += weights_length[i].weight* weights_radius[k].weight; 362 } 363 } 364 if (norm != 0){ 365 //return the averaged value 366 rad_out = sum/norm;} 367 else{ 368 //return normal value 369 //Note: output of "DiamCyl(dp.length,dp.radius)" is DIAMETER. 370 rad_out = DiamCyl(dp.length,dp.radius)/2.0;} 371 372 return rad_out; 373 } -
sansmodels/src/c_models/lamellar.cpp
r67424cd r82c11d3 18 18 * sansmodels/src/libigor 19 19 * 20 * TODO: refactor so that we pull in the old sansmodels.c_extensions21 20 */ 22 21 23 22 #include <math.h> 24 #include "models.hh"25 23 #include "parameters.hh" 26 24 #include <stdio.h> 27 25 using namespace std; 26 #include "lamellar.h" 28 27 29 extern "C" { 30 // #include "libCylinder.h" 31 #include "lamellar.h" 28 /* LamellarFFX : calculates the form factor of a lamellar structure - no S(q) effects included 29 -NO polydispersion included 30 */ 31 static double lamellar_kernel(double dp[], double q){ 32 double scale,del,sld_bi,sld_sol,contr,bkg; //local variables of coefficient wave 33 double inten, qval,Pq; 34 double Pi; 35 36 37 Pi = 4.0*atan(1.0); 38 scale = dp[0]; 39 del = dp[1]; 40 sld_bi = dp[2]; 41 sld_sol = dp[3]; 42 bkg = dp[4]; 43 qval = q; 44 contr = sld_bi -sld_sol; 45 46 Pq = 2.0*contr*contr/qval/qval*(1.0-cos(qval*del)); 47 48 inten = 2.0*Pi*scale*Pq/(qval*qval); //this is now dimensionless... 49 50 inten /= del; //normalize by the thickness (in A) 51 52 inten *= 1.0e8; // 1/A to 1/cm 53 54 return(inten+bkg); 32 55 } 33 56 … … 39 62 sld_sol = Parameter(6.3e-6); 40 63 background = Parameter(0.0); 41 42 64 } 43 65 -
sansmodels/src/c_models/lamellarFF_HG.cpp
r67424cd r82c11d3 18 18 * sansmodels/src/libigor 19 19 * 20 * TODO: refactor so that we pull in the old sansmodels.c_extensions21 20 */ 22 21 23 22 #include <math.h> 24 #include "models.hh"25 23 #include "parameters.hh" 26 24 #include <stdio.h> 27 25 using namespace std; 26 #include "lamellarFF_HG.h" 28 27 29 28 extern "C" { 30 #include "libCylinder.h" 31 #include "lamellarFF_HG.h" 29 #include "libCylinder.h" 32 30 } 33 31 34 32 LamellarFFHGModel :: LamellarFFHGModel() { 35 36 37 38 39 40 41 42 43 33 scale = Parameter(1.0); 34 t_length = Parameter(15.0, true); 35 t_length.set_min(0.0); 36 h_thickness = Parameter(10.0, true); 37 h_thickness.set_min(0.0); 38 sld_tail = Parameter(4e-7); 39 sld_head = Parameter(3e-6); 40 sld_solvent = Parameter(6e-6); 41 background = Parameter(0.0); 44 42 45 43 } … … 52 50 */ 53 51 double LamellarFFHGModel :: operator()(double q) { 54 52 double dp[7]; 55 53 56 57 58 59 60 61 62 63 64 54 // Fill parameter array for IGOR library 55 // Add the background after averaging 56 dp[0] = scale(); 57 dp[1] = t_length(); 58 dp[2] = h_thickness(); 59 dp[3] = sld_tail(); 60 dp[4] = sld_head(); 61 dp[5] = sld_solvent(); 62 dp[6] = 0.0; 65 63 66 67 68 64 // Get the dispersion points for the tail length 65 vector<WeightPoint> weights_t_length; 66 t_length.get_weights(weights_t_length); 69 67 70 71 72 68 // Get the dispersion points for the head thickness 69 vector<WeightPoint> weights_h_thickness; 70 h_thickness.get_weights(weights_h_thickness); 73 71 74 75 76 72 // Perform the computation, with all weight points 73 double sum = 0.0; 74 double norm = 0.0; 77 75 78 79 80 76 // Loop over semi axis A weight points 77 for(int i=0; i< (int)weights_t_length.size(); i++) { 78 dp[1] = weights_t_length[i].value; 81 79 82 83 80 for (int j=0; j< (int)weights_h_thickness.size(); j++){ 81 dp[2] = weights_h_thickness[j].value; 84 82 85 86 87 83 sum += weights_t_length[i].weight* weights_h_thickness[j].weight*LamellarFF_HG(dp, q); 84 norm += weights_t_length[i].weight* weights_h_thickness[j].weight; 85 } 88 86 89 90 87 } 88 return sum/norm + background(); 91 89 } 92 90 … … 99 97 100 98 double LamellarFFHGModel :: operator()(double qx, double qy) { 101 102 99 double q = sqrt(qx*qx + qy*qy); 100 return (*this).operator()(q); 103 101 } 104 102 … … 111 109 */ 112 110 double LamellarFFHGModel :: evaluate_rphi(double q, double phi) { 113 111 return (*this).operator()(q); 114 112 } 115 113 /** … … 118 116 */ 119 117 double LamellarFFHGModel :: calculate_ER() { 120 //NOT implemented yet!!!121 118 //NOT implemented yet!!! 119 return 0.0; 122 120 } -
sansmodels/src/c_models/lamellarPC.cpp
r67424cd r82c11d3 20 20 21 21 #include <math.h> 22 #include "models.hh"23 22 #include "parameters.hh" 24 23 #include <stdio.h> 25 24 using namespace std; 25 #include "lamellarPC.h" 26 26 27 27 extern "C" { 28 #include "libCylinder.h" 29 #include "lamellarPC.h" 28 #include "libCylinder.h" 30 29 } 31 30 32 31 LamellarPCrystalModel :: LamellarPCrystalModel() { 33 34 35 36 37 38 39 40 41 42 32 scale = Parameter(1.0); 33 thickness = Parameter(33.0, true); 34 thickness.set_min(0.0); 35 Nlayers = Parameter(20.0, true); 36 Nlayers.set_min(0.0); 37 spacing = Parameter(250); 38 pd_spacing = Parameter(0.0); 39 sld_layer = Parameter(1.0e-6); 40 sld_solvent = Parameter(6.34e-6); 41 background = Parameter(0.0); 43 42 44 43 } … … 51 50 */ 52 51 double LamellarPCrystalModel :: operator()(double q) { 53 52 double dp[8]; 54 53 55 56 57 58 59 60 61 62 63 64 54 // Fill parameter array for IGOR library 55 // Add the background after averaging 56 dp[0] = scale(); 57 dp[1] = thickness(); 58 dp[2] = Nlayers(); 59 dp[3] = spacing(); 60 dp[4] = pd_spacing(); 61 dp[5] = sld_layer(); 62 dp[6] = sld_solvent(); 63 dp[7] = 0.0; // Do not apply background here. 65 64 66 67 68 65 // Get the dispersion points for the head thickness 66 vector<WeightPoint> weights_thickness; 67 thickness.get_weights(weights_thickness); 69 68 70 71 72 73 69 // Let's provide from the func which is more accurate especially for small q region. 70 // Get the dispersion points for the tail length 71 //vector<WeightPoint> weights_spacing; 72 //spacing.get_weights(weights_spacing); 74 73 75 76 77 74 // Perform the computation, with all weight points 75 double sum = 0.0; 76 double norm = 0.0; 78 77 79 80 81 82 83 84 85 86 87 88 89 78 // Loop over thickness and spacing weight points 79 for(int i=0; i< (int)weights_thickness.size(); i++) { 80 dp[1] = weights_thickness[i].value; 81 //for (int j=0; j< (int)weights_spacing.size(); j++){ 82 //dp[3] = weights_spacing[j].value; 83 sum += weights_thickness[i].weight*Lamellar_ParaCrystal(dp, q); 84 norm += weights_thickness[i].weight; 85 //} 86 } 87 //apply norm and background 88 return sum/norm + background(); 90 89 } 91 90 … … 98 97 99 98 double LamellarPCrystalModel :: operator()(double qx, double qy) { 100 101 99 double q = sqrt(qx*qx + qy*qy); 100 return (*this).operator()(q); 102 101 } 103 102 … … 110 109 */ 111 110 double LamellarPCrystalModel :: evaluate_rphi(double q, double phi) { 112 111 return (*this).operator()(q); 113 112 } 114 113 /** … … 117 116 */ 118 117 double LamellarPCrystalModel :: calculate_ER() { 119 //NOT implemented yet!!!120 118 //NOT implemented yet!!! 119 return 0.0; 121 120 } -
sansmodels/src/c_models/lamellarPS.cpp
r67424cd r82c11d3 23 23 24 24 #include <math.h> 25 #include "models.hh"26 25 #include "parameters.hh" 27 26 #include <stdio.h> 27 #include <stdlib.h> 28 28 using namespace std; 29 #include "lamellarPS.h" 29 30 30 31 extern "C" { 31 #include "libCylinder.h" 32 #include "lamellarPS.h" 32 #include "libCylinder.h" 33 } 34 35 /*LamellarPS_kernel() was moved from libigor to get rid of polydipersity in del(thickness) that we provide from control panel. 36 LamellarPSX : calculates the form factor of a lamellar structure - with S(q) effects included 37 ------- 38 ------- resolution effects ARE NOT included, but only a CONSTANT default value, not the real q-dependent resolution!! 39 40 */ 41 static double LamellarPS_kernel(double dp[], double q) 42 { 43 double scale,dd,del,sld_bi,sld_sol,contr,NN,Cp,bkg; //local variables of coefficient wave 44 double inten, qval,Pq,Sq,alpha,temp,t1,t2,t3,dQ; 45 double Pi,Euler,dQDefault,fii; 46 int ii,NNint; 47 Euler = 0.5772156649; // Euler's constant 48 dQDefault = 0.0; //[=] 1/A, q-resolution, default value 49 dQ = dQDefault; 50 51 Pi = 4.0*atan(1.0); 52 qval = q; 53 54 scale = dp[0]; 55 dd = dp[1]; 56 del = dp[2]; 57 sld_bi = dp[3]; 58 sld_sol = dp[4]; 59 NN = trunc(dp[5]); //be sure that NN is an integer 60 Cp = dp[6]; 61 bkg = dp[7]; 62 63 contr = sld_bi - sld_sol; 64 65 Pq = 2.0*contr*contr/qval/qval*(1.0-cos(qval*del)); 66 67 NNint = (int)NN; //cast to an integer for the loop 68 ii=0; 69 Sq = 0.0; 70 for(ii=1;ii<(NNint-1);ii+=1) { 71 72 fii = (double)ii; //do I really need to do this? 73 74 temp = 0.0; 75 alpha = Cp/4.0/Pi/Pi*(log(Pi*ii) + Euler); 76 t1 = 2.0*dQ*dQ*dd*dd*alpha; 77 t2 = 2.0*qval*qval*dd*dd*alpha; 78 t3 = dQ*dQ*dd*dd*ii*ii; 79 80 temp = 1.0-ii/NN; 81 temp *= cos(dd*qval*ii/(1.0+t1)); 82 temp *= exp(-1.0*(t2 + t3)/(2.0*(1.0+t1)) ); 83 temp /= sqrt(1.0+t1); 84 85 Sq += temp; 86 } 87 88 Sq *= 2.0; 89 Sq += 1.0; 90 91 inten = 2.0*Pi*scale*Pq*Sq/(dd*qval*qval); 92 93 inten *= 1.0e8; // 1/A to 1/cm 94 95 return(inten+bkg); 33 96 } 34 97 35 98 LamellarPSModel :: LamellarPSModel() { 36 37 38 39 40 41 42 43 44 45 99 scale = Parameter(1.0); 100 spacing = Parameter(400.0, true); 101 spacing.set_min(0.0); 102 delta = Parameter(30.0); 103 delta.set_min(0.0); 104 sld_bi = Parameter(6.3e-6); 105 sld_sol = Parameter(1.0e-6); 106 n_plates = Parameter(20.0); 107 caille = Parameter(0.1); 108 background = Parameter(0.0); 46 109 47 110 } … … 54 117 */ 55 118 double LamellarPSModel :: operator()(double q) { 56 119 double dp[8]; 57 120 58 59 60 61 62 63 64 65 66 67 121 // Fill parameter array for IGOR library 122 // Add the background after averaging 123 dp[0] = scale(); 124 dp[1] = spacing(); 125 dp[2] = delta(); 126 dp[3] = sld_bi(); 127 dp[4] = sld_sol(); 128 dp[5] = n_plates(); 129 dp[6] = caille(); 130 dp[7] = 0.0; 68 131 69 132 70 71 72 73 74 133 // Get the dispersion points for spacing and delta (thickness) 134 vector<WeightPoint> weights_spacing; 135 spacing.get_weights(weights_spacing); 136 vector<WeightPoint> weights_delta; 137 delta.get_weights(weights_delta); 75 138 76 77 78 139 // Perform the computation, with all weight points 140 double sum = 0.0; 141 double norm = 0.0; 79 142 80 81 82 83 84 143 // Loop over short_edgeA weight points 144 for(int i=0; i< (int)weights_spacing.size(); i++) { 145 dp[1] = weights_spacing[i].value; 146 for(int j=0; j< (int)weights_spacing.size(); j++) { 147 dp[2] = weights_delta[i].value; 85 148 86 87 88 89 90 149 sum += weights_spacing[i].weight * weights_delta[j].weight * LamellarPS_kernel(dp, q); 150 norm += weights_spacing[i].weight * weights_delta[j].weight; 151 } 152 } 153 return sum/norm + background(); 91 154 } 92 155 /** … … 97 160 */ 98 161 double LamellarPSModel :: operator()(double qx, double qy) { 99 100 162 double q = sqrt(qx*qx + qy*qy); 163 return (*this).operator()(q); 101 164 } 102 165 … … 109 172 */ 110 173 double LamellarPSModel :: evaluate_rphi(double q, double phi) { 111 174 return (*this).operator()(q); 112 175 } 113 176 /** … … 116 179 */ 117 180 double LamellarPSModel :: calculate_ER() { 118 //NOT implemented yet!!!119 181 //NOT implemented yet!!! 182 return 0.0; 120 183 } 121 184 -
sansmodels/src/c_models/lamellarPS_HG.cpp
r67424cd r82c11d3 18 18 * sansmodels/src/libigor 19 19 * 20 * TODO: refactor so that we pull in the old sansmodels.c_extensions21 20 * TODO: add 2D function 22 21 */ 23 22 24 23 #include <math.h> 25 #include "models.hh"26 24 #include "parameters.hh" 27 25 #include <stdio.h> 28 26 using namespace std; 27 #include "lamellarPS_HG.h" 29 28 30 29 extern "C" { 31 30 #include "libCylinder.h" 32 #include "lamellarPS_HG.h"33 31 } 34 32 … … 137 135 return 0.0; 138 136 } 139 140 /*141 double LamellarPSHGModel :: operator()(double qx, double qy) {142 LamellarPSHGParameters dp;143 // Fill parameter array144 dp.scale = scale();145 dp.spacing = spacing();146 dp.deltaT = deltaT();147 dp.deltaH = deltaH();148 dp.sld_tail = sld_tail();149 dp.sld_head = sld_head();150 dp.sld_solvent = sld_solvent();151 dp.n_plates = n_plates();152 dp.caille = caille();153 dp.background = background();154 155 // Get the dispersion points for the deltaT156 vector<WeightPoint> weights_deltaT;157 deltaT.get_weights(weights_deltaT);158 159 // Get the dispersion points for the deltaH160 vector<WeightPoint> weights_deltaH;161 deltaH.get_weights(weights_deltaH);162 163 // Perform the computation, with all weight points164 double sum = 0.0;165 double norm = 0.0;166 167 // Loop over deltaT weight points168 for(int i=0; i< (int)weights_deltaT.size(); i++) {169 dp.deltaT = weights_deltaT[i].value;170 171 // Loop over deltaH weight points172 for(int j=0; j< (int)weights_deltaH.size(); j++) {173 dp.deltaH = weights_deltaH[j].value;174 175 sum += weights_deltaT[i].weight *weights_deltaH[j].weight *lamellarPS_HG_analytical_2DXY(&dp, qx, qy);176 norm += weights_deltaT[i].weight * weights_deltaH[j].weight;177 }178 }179 return sum/norm + background();180 }181 */182 183 -
sansmodels/src/c_models/multishell.cpp
r67424cd r82c11d3 21 21 22 22 #include <math.h> 23 #include "models.hh"24 23 #include "parameters.hh" 25 24 #include <stdio.h> 26 25 using namespace std; 26 #include "multishell.h" 27 27 28 28 extern "C" { 29 #include "libSphere.h" 30 #include "multishell.h" 29 #include "libSphere.h" 31 30 } 32 31 32 typedef struct { 33 double scale; 34 double core_radius; 35 double s_thickness; 36 double w_thickness; 37 double core_sld; 38 double shell_sld; 39 double n_pairs; 40 double background; 41 42 } MultiShellParameters; 43 33 44 MultiShellModel :: MultiShellModel() { 34 35 36 37 38 39 40 41 42 43 44 45 scale = Parameter(1.0); 46 core_radius = Parameter(60.0, true); 47 core_radius.set_min(0.0); 48 s_thickness = Parameter(10.0, true); 49 s_thickness.set_min(0.0); 50 w_thickness = Parameter(10.0, true); 51 w_thickness.set_min(0.0); 52 core_sld = Parameter(6.4e-6); 53 shell_sld = Parameter(4.0e-7); 54 n_pairs = Parameter(2); 55 background = Parameter(0.0); 45 56 } 46 57 … … 52 63 */ 53 64 double MultiShellModel :: operator()(double q) { 54 65 double dp[8]; 55 66 56 57 58 59 60 61 62 63 64 65 67 // Fill parameter array for IGOR library 68 // Add the background after averaging 69 dp[0] = scale(); 70 dp[1] = core_radius(); 71 dp[2] = s_thickness(); 72 dp[3] = w_thickness(); 73 dp[4] = core_sld(); 74 dp[5] = shell_sld(); 75 dp[6] = n_pairs(); 76 dp[7] = 0.0; 66 77 67 68 69 78 // Get the dispersion points for the core radius 79 vector<WeightPoint> weights_core_radius; 80 core_radius.get_weights(weights_core_radius); 70 81 71 72 73 82 // Get the dispersion points for the s_thickness 83 vector<WeightPoint> weights_s_thickness; 84 s_thickness.get_weights(weights_s_thickness); 74 85 75 76 77 86 // Get the dispersion points for the w_thickness 87 vector<WeightPoint> weights_w_thickness; 88 w_thickness.get_weights(weights_w_thickness); 78 89 79 80 81 82 90 // Perform the computation, with all weight points 91 double sum = 0.0; 92 double norm = 0.0; 93 double vol = 0.0; 83 94 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 95 // Loop over radius weight points 96 for(int i=0; i< (int)weights_core_radius.size(); i++) { 97 dp[1] = weights_core_radius[i].value; 98 for(int j=0; j< (int)weights_s_thickness.size(); j++){ 99 dp[2] = weights_s_thickness[j].value; 100 for(int k=0; k< (int)weights_w_thickness.size(); k++){ 101 dp[3] = weights_w_thickness[k].value; 102 //Un-normalize SphereForm by volume 103 sum += weights_core_radius[i].weight*weights_s_thickness[j].weight 104 *weights_w_thickness[k].weight* MultiShell(dp, q) 105 *pow(weights_core_radius[i].value+dp[6]*weights_s_thickness[j].value+(dp[6]-1)*weights_w_thickness[k].value,3); 106 //Find average volume 107 vol += weights_core_radius[i].weight*weights_s_thickness[j].weight 108 *weights_w_thickness[k].weight 109 *pow(weights_core_radius[i].value+dp[6]*weights_s_thickness[j].value+(dp[6]-1)*weights_w_thickness[k].value,3); 110 norm += weights_core_radius[i].weight*weights_s_thickness[j].weight 111 *weights_w_thickness[k].weight; 112 } 113 } 114 } 115 if (vol != 0.0 && norm != 0.0) { 116 //Re-normalize by avg volume 117 sum = sum/(vol/norm);} 118 return sum/norm + background(); 108 119 } 109 120 … … 115 126 */ 116 127 double MultiShellModel :: operator()(double qx, double qy) { 117 118 128 double q = sqrt(qx*qx + qy*qy); 129 return (*this).operator()(q); 119 130 } 120 131 … … 127 138 */ 128 139 double MultiShellModel :: evaluate_rphi(double q, double phi) { 129 140 return (*this).operator()(q); 130 141 } 131 142 /** … … 134 145 */ 135 146 double MultiShellModel :: calculate_ER() { 136 147 MultiShellParameters dp; 137 148 138 139 140 141 149 dp.core_radius = core_radius(); 150 dp.s_thickness = s_thickness(); 151 dp.w_thickness = w_thickness(); 152 dp.n_pairs = n_pairs(); 142 153 143 154 double rad_out = 0.0; 144 155 145 146 147 148 149 150 156 // Perform the computation, with all weight points 157 double sum = 0.0; 158 double norm = 0.0; 159 if (dp.n_pairs <= 0.0 ){ 160 dp.n_pairs = 0.0; 161 } 151 162 152 153 154 163 // Get the dispersion points for the core radius 164 vector<WeightPoint> weights_core_radius; 165 core_radius.get_weights(weights_core_radius); 155 166 156 157 158 167 // Get the dispersion points for the s_thickness 168 vector<WeightPoint> weights_s_thickness; 169 s_thickness.get_weights(weights_s_thickness); 159 170 160 161 162 171 // Get the dispersion points for the w_thickness 172 vector<WeightPoint> weights_w_thickness; 173 w_thickness.get_weights(weights_w_thickness); 163 174 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 175 // Loop over major shell weight points 176 for(int i=0; i< (int)weights_s_thickness.size(); i++) { 177 dp.s_thickness = weights_s_thickness[i].value; 178 for(int j=0; j< (int)weights_w_thickness.size(); j++) { 179 dp.w_thickness = weights_w_thickness[j].value; 180 for(int k=0; k< (int)weights_core_radius.size(); k++) { 181 dp.core_radius = weights_core_radius[k].value; 182 sum += weights_s_thickness[i].weight*weights_w_thickness[j].weight 183 * weights_core_radius[k].weight*(dp.core_radius+dp.n_pairs*dp.s_thickness+(dp.n_pairs-1.0)*dp.w_thickness); 184 norm += weights_s_thickness[i].weight*weights_w_thickness[j].weight* weights_core_radius[k].weight; 185 } 186 } 187 } 188 if (norm != 0){ 189 //return the averaged value 190 rad_out = sum/norm;} 191 else{ 192 //return normal value 193 rad_out = (dp.core_radius+dp.n_pairs*dp.s_thickness+(dp.n_pairs-1.0)*dp.w_thickness);} 183 194 184 195 return rad_out; 185 196 } -
sansmodels/src/c_models/parallelepiped.cpp
r8343e18 r82c11d3 22 22 23 23 #include <math.h> 24 #include "models.hh"25 24 #include "parameters.hh" 26 25 #include <stdio.h> -
sansmodels/src/c_models/polygausscoil.cpp
r67424cd r82c11d3 21 21 22 22 #include <math.h> 23 #include "models.hh"24 23 #include "parameters.hh" 25 24 #include <stdio.h> 26 25 using namespace std; 26 #include "polygausscoil.h" 27 27 28 28 extern "C" { 29 29 #include "libTwoPhase.h" 30 #include "polygausscoil.h"31 30 } 32 31 -
sansmodels/src/c_models/sc.cpp
r6e10cff r82c11d3 21 21 22 22 #include <math.h> 23 #include "models.hh"24 23 #include "parameters.hh" 25 24 #include <stdio.h> -
sansmodels/src/c_models/sphere.cpp
ra8eab1c r82c11d3 21 21 22 22 #include <math.h> 23 #include "models.hh"24 23 #include "parameters.hh" 25 24 #include <stdio.h> -
sansmodels/src/c_models/spheroid.cpp
r67424cd r82c11d3 18 18 * sansmodels/src/libigor 19 19 * 20 * TODO: refactor so that we pull in the old sansmodels.c_extensions21 20 */ 22 21 23 22 #include <math.h> 24 #include "models.hh"25 23 #include "parameters.hh" 26 24 #include <stdio.h> 25 #include <stdlib.h> 27 26 using namespace std; 27 #include "spheroid.h" 28 28 29 29 extern "C" { 30 #include "libCylinder.h" 31 #include "libStructureFactor.h" 32 #include "spheroid.h" 30 #include "libCylinder.h" 31 #include "libStructureFactor.h" 32 } 33 34 typedef struct { 35 double scale; 36 double equat_core; 37 double polar_core; 38 double equat_shell; 39 double polar_shell; 40 double sld_core; 41 double sld_shell; 42 double sld_solvent; 43 double background; 44 double axis_theta; 45 double axis_phi; 46 47 } SpheroidParameters; 48 49 /** 50 * Function to evaluate 2D scattering function 51 * @param pars: parameters of the prolate 52 * @param q: q-value 53 * @param q_x: q_x / q 54 * @param q_y: q_y / q 55 * @return: function value 56 */ 57 static double spheroid_analytical_2D_scaled(SpheroidParameters *pars, double q, double q_x, double q_y) { 58 59 double cyl_x, cyl_y, cyl_z; 60 double q_z; 61 double alpha, vol, cos_val; 62 double answer; 63 double Pi = 4.0*atan(1.0); 64 double sldcs,sldss; 65 66 //convert angle degree to radian 67 double theta = pars->axis_theta * Pi/180.0; 68 double phi = pars->axis_phi * Pi/180.0; 69 70 71 // ellipsoid orientation, the axis of the rotation is consistent with the ploar axis. 72 cyl_x = sin(theta) * cos(phi); 73 cyl_y = sin(theta) * sin(phi); 74 cyl_z = cos(theta); 75 //del sld 76 sldcs = pars->sld_core - pars->sld_shell; 77 sldss = pars->sld_shell- pars->sld_solvent; 78 79 // q vector 80 q_z = 0; 81 82 // Compute the angle btw vector q and the 83 // axis of the cylinder 84 cos_val = cyl_x*q_x + cyl_y*q_y + cyl_z*q_z; 85 86 // The following test should always pass 87 if (fabs(cos_val)>1.0) { 88 printf("cyl_ana_2D: Unexpected error: cos(alpha)>1\n"); 89 return 0; 90 } 91 92 // Note: cos(alpha) = 0 and 1 will get an 93 // undefined value from CylKernel 94 alpha = acos( cos_val ); 95 96 // Call the IGOR library function to get the kernel: MUST use gfn4 not gf2 because of the def of params. 97 answer = gfn4(cos_val,pars->equat_core,pars->polar_core,pars->equat_shell,pars->polar_shell,sldcs,sldss,q); 98 //It seems that it should be normalized somehow. How??? 99 100 //normalize by cylinder volume 101 //NOTE that for this (Fournet) definition of the integral, one must MULTIPLY by Vcyl 102 vol = 4.0*Pi/3.0*pars->equat_shell*pars->equat_shell*pars->polar_shell; 103 answer /= vol; 104 105 //convert to [cm-1] 106 answer *= 1.0e8; 107 108 //Scale 109 answer *= pars->scale; 110 111 // add in the background 112 answer += pars->background; 113 114 return answer; 33 115 } 34 116 35 117 CoreShellEllipsoidModel :: 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 sld_core = Parameter(2e-6); 46 sld_shell = Parameter(1e-6); 47 sld_solvent = Parameter(6.3e-6); 48 background = Parameter(0.0); 49 axis_theta = Parameter(0.0, true); 50 axis_phi = Parameter(0.0, true); 51 118 scale = Parameter(1.0); 119 equat_core = Parameter(200.0, true); 120 equat_core.set_min(0.0); 121 polar_core = Parameter(20.0, true); 122 polar_core.set_min(0.0); 123 equat_shell = Parameter(250.0, true); 124 equat_shell.set_min(0.0); 125 polar_shell = Parameter(30.0, true); 126 polar_shell.set_min(0.0); 127 sld_core = Parameter(2e-6); 128 sld_shell = Parameter(1e-6); 129 sld_solvent = Parameter(6.3e-6); 130 background = Parameter(0.0); 131 axis_theta = Parameter(0.0, true); 132 axis_phi = Parameter(0.0, true); 133 134 } 135 136 137 /** 138 * Function to evaluate 2D scattering function 139 * @param pars: parameters of the prolate 140 * @param q: q-value 141 * @return: function value 142 */ 143 static double spheroid_analytical_2DXY(SpheroidParameters *pars, double qx, double qy) { 144 double q; 145 q = sqrt(qx*qx+qy*qy); 146 return spheroid_analytical_2D_scaled(pars, q, qx/q, qy/q); 52 147 } 53 148 … … 59 154 */ 60 155 double CoreShellEllipsoidModel :: 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 122 123 124 125 126 127 128 129 130 156 double dp[9]; 157 158 // Fill parameter array for IGOR library 159 // Add the background after averaging 160 dp[0] = scale(); 161 dp[1] = equat_core(); 162 dp[2] = polar_core(); 163 dp[3] = equat_shell(); 164 dp[4] = polar_shell(); 165 dp[5] = sld_core(); 166 dp[6] = sld_shell(); 167 dp[7] = sld_solvent(); 168 dp[8] = 0.0; 169 170 // Get the dispersion points for the major core 171 vector<WeightPoint> weights_equat_core; 172 equat_core.get_weights(weights_equat_core); 173 174 // Get the dispersion points for the minor core 175 vector<WeightPoint> weights_polar_core; 176 polar_core.get_weights(weights_polar_core); 177 178 // Get the dispersion points for the major shell 179 vector<WeightPoint> weights_equat_shell; 180 equat_shell.get_weights(weights_equat_shell); 181 182 // Get the dispersion points for the minor_shell 183 vector<WeightPoint> weights_polar_shell; 184 polar_shell.get_weights(weights_polar_shell); 185 186 187 // Perform the computation, with all weight points 188 double sum = 0.0; 189 double norm = 0.0; 190 double vol = 0.0; 191 192 // Loop over major core weight points 193 for(int i=0; i<(int)weights_equat_core.size(); i++) { 194 dp[1] = weights_equat_core[i].value; 195 196 // Loop over minor core weight points 197 for(int j=0; j<(int)weights_polar_core.size(); j++) { 198 dp[2] = weights_polar_core[j].value; 199 200 // Loop over major shell weight points 201 for(int k=0; k<(int)weights_equat_shell.size(); k++) { 202 dp[3] = weights_equat_shell[k].value; 203 204 // Loop over minor shell weight points 205 for(int l=0; l<(int)weights_polar_shell.size(); l++) { 206 dp[4] = weights_polar_shell[l].value; 207 //Un-normalize by volume 208 sum += weights_equat_core[i].weight* weights_polar_core[j].weight * weights_equat_shell[k].weight 209 * weights_polar_shell[l].weight * OblateForm(dp, q) 210 * pow(weights_equat_shell[k].value,2)*weights_polar_shell[l].value; 211 //Find average volume 212 vol += weights_equat_core[i].weight* weights_polar_core[j].weight 213 * weights_equat_shell[k].weight 214 * weights_polar_shell[l].weight 215 * pow(weights_equat_shell[k].value,2)*weights_polar_shell[l].value; 216 norm += weights_equat_core[i].weight* weights_polar_core[j].weight * weights_equat_shell[k].weight 217 * weights_polar_shell[l].weight; 218 } 219 } 220 } 221 } 222 if (vol != 0.0 && norm != 0.0) { 223 //Re-normalize by avg volume 224 sum = sum/(vol/norm);} 225 return sum/norm + background(); 131 226 } 132 227 … … 143 238 return (*this).operator()(q); 144 239 } 145 */240 */ 146 241 147 242 /** … … 153 248 */ 154 249 double CoreShellEllipsoidModel :: evaluate_rphi(double q, double phi) { 155 156 157 250 double qx = q*cos(phi); 251 double qy = q*sin(phi); 252 return (*this).operator()(qx, qy); 158 253 } 159 254 … … 165 260 */ 166 261 double CoreShellEllipsoidModel :: operator()(double qx, double qy) { 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 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 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 262 SpheroidParameters dp; 263 // Fill parameter array 264 dp.scale = scale(); 265 dp.equat_core = equat_core(); 266 dp.polar_core = polar_core(); 267 dp.equat_shell = equat_shell(); 268 dp.polar_shell = polar_shell(); 269 dp.sld_core = sld_core(); 270 dp.sld_shell = sld_shell(); 271 dp.sld_solvent = sld_solvent(); 272 dp.background = 0.0; 273 dp.axis_theta = axis_theta(); 274 dp.axis_phi = axis_phi(); 275 276 // Get the dispersion points for the major core 277 vector<WeightPoint> weights_equat_core; 278 equat_core.get_weights(weights_equat_core); 279 280 // Get the dispersion points for the minor core 281 vector<WeightPoint> weights_polar_core; 282 polar_core.get_weights(weights_polar_core); 283 284 // Get the dispersion points for the major shell 285 vector<WeightPoint> weights_equat_shell; 286 equat_shell.get_weights(weights_equat_shell); 287 288 // Get the dispersion points for the minor shell 289 vector<WeightPoint> weights_polar_shell; 290 polar_shell.get_weights(weights_polar_shell); 291 292 293 // Get angular averaging for theta 294 vector<WeightPoint> weights_theta; 295 axis_theta.get_weights(weights_theta); 296 297 // Get angular averaging for phi 298 vector<WeightPoint> weights_phi; 299 axis_phi.get_weights(weights_phi); 300 301 // Perform the computation, with all weight points 302 double sum = 0.0; 303 double norm = 0.0; 304 double norm_vol = 0.0; 305 double vol = 0.0; 306 double pi = 4.0*atan(1.0); 307 // Loop over major core weight points 308 for(int i=0; i< (int)weights_equat_core.size(); i++) { 309 dp.equat_core = weights_equat_core[i].value; 310 311 // Loop over minor core weight points 312 for(int j=0; j< (int)weights_polar_core.size(); j++) { 313 dp.polar_core = weights_polar_core[j].value; 314 315 // Loop over major shell weight points 316 for(int k=0; k< (int)weights_equat_shell.size(); k++) { 317 dp.equat_shell = weights_equat_shell[i].value; 318 319 // Loop over minor shell weight points 320 for(int l=0; l< (int)weights_polar_shell.size(); l++) { 321 dp.polar_shell = weights_polar_shell[l].value; 322 323 // Average over theta distribution 324 for(int m=0; m< (int)weights_theta.size(); m++) { 325 dp.axis_theta = weights_theta[m].value; 326 327 // Average over phi distribution 328 for(int n=0; n< (int)weights_phi.size(); n++) { 329 dp.axis_phi = weights_phi[n].value; 330 //Un-normalize by volume 331 double _ptvalue = weights_equat_core[i].weight *weights_polar_core[j].weight 332 * weights_equat_shell[k].weight * weights_polar_shell[l].weight 333 * weights_theta[m].weight 334 * weights_phi[n].weight 335 * spheroid_analytical_2DXY(&dp, qx, qy) 336 * pow(weights_equat_shell[k].value,2)*weights_polar_shell[l].value; 337 if (weights_theta.size()>1) { 338 _ptvalue *= fabs(sin(weights_theta[m].value*pi/180.0)); 339 } 340 sum += _ptvalue; 341 //Find average volume 342 vol += weights_equat_shell[k].weight 343 * weights_polar_shell[l].weight 344 * pow(weights_equat_shell[k].value,2)*weights_polar_shell[l].value; 345 //Find norm for volume 346 norm_vol += weights_equat_shell[k].weight 347 * weights_polar_shell[l].weight; 348 349 norm += weights_equat_core[i].weight *weights_polar_core[j].weight 350 * weights_equat_shell[k].weight * weights_polar_shell[l].weight 351 * weights_theta[m].weight * weights_phi[n].weight; 352 } 353 } 354 } 355 } 356 } 357 } 358 // Averaging in theta needs an extra normalization 359 // factor to account for the sin(theta) term in the 360 // integration (see documentation). 361 if (weights_theta.size()>1) norm = norm / asin(1.0); 362 363 if (vol != 0.0 && norm_vol != 0.0) { 364 //Re-normalize by avg volume 365 sum = sum/(vol/norm_vol);} 366 367 return sum/norm + background(); 273 368 } 274 369 … … 278 373 */ 279 374 double CoreShellEllipsoidModel :: calculate_ER() { 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 } 375 SpheroidParameters dp; 376 377 dp.equat_shell = equat_shell(); 378 dp.polar_shell = polar_shell(); 379 380 double rad_out = 0.0; 381 382 // Perform the computation, with all weight points 383 double sum = 0.0; 384 double norm = 0.0; 385 386 // Get the dispersion points for the major shell 387 vector<WeightPoint> weights_equat_shell; 388 equat_shell.get_weights(weights_equat_shell); 389 390 // Get the dispersion points for the minor shell 391 vector<WeightPoint> weights_polar_shell; 392 polar_shell.get_weights(weights_polar_shell); 393 394 // Loop over major shell weight points 395 for(int i=0; i< (int)weights_equat_shell.size(); i++) { 396 dp.equat_shell = weights_equat_shell[i].value; 397 for(int k=0; k< (int)weights_polar_shell.size(); k++) { 398 dp.polar_shell = weights_polar_shell[k].value; 399 //Note: output of "DiamEllip(dp.polar_shell,dp.equat_shell)" is DIAMETER. 400 sum +=weights_equat_shell[i].weight 401 * weights_polar_shell[k].weight*DiamEllip(dp.polar_shell,dp.equat_shell)/2.0; 402 norm += weights_equat_shell[i].weight* weights_polar_shell[k].weight; 403 } 404 } 405 if (norm != 0){ 406 //return the averaged value 407 rad_out = sum/norm;} 408 else{ 409 //return normal value 410 //Note: output of "DiamEllip(dp.polar_shell,dp.equat_shell)" is DIAMETER. 411 rad_out = DiamEllip(dp.polar_shell,dp.equat_shell)/2.0;} 412 413 return rad_out; 414 } -
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 } -
sansmodels/src/c_models/triaxialellipsoid.cpp
r67424cd r82c11d3 18 18 * sansmodels/src/libigor 19 19 * 20 * TODO: refactor so that we pull in the old sansmodels.c_extensions21 20 */ 22 21 23 22 #include <math.h> 24 #include "models.hh"25 23 #include "parameters.hh" 26 24 #include <stdio.h> 25 #include <stdlib.h> 27 26 using namespace std; 27 #include "triaxial_ellipsoid.h" 28 28 29 29 extern "C" { 30 #include "libCylinder.h" 31 #include "libStructureFactor.h" 32 #include "triaxial_ellipsoid.h" 33 } 30 #include "libCylinder.h" 31 #include "libStructureFactor.h" 32 } 33 34 typedef struct { 35 double scale; 36 double semi_axisA; 37 double semi_axisB; 38 double semi_axisC; 39 double sldEll; 40 double sldSolv; 41 double background; 42 double axis_theta; 43 double axis_phi; 44 double axis_psi; 45 46 } TriaxialEllipsoidParameters; 47 48 static double triaxial_ellipsoid_kernel(TriaxialEllipsoidParameters *pars, double q, double alpha, double nu) { 49 double t,a,b,c; 50 double kernel; 51 52 a = pars->semi_axisA ; 53 b = pars->semi_axisB ; 54 c = pars->semi_axisC ; 55 56 t = q * sqrt(a*a*cos(nu)*cos(nu)+b*b*sin(nu)*sin(nu)*sin(alpha)*sin(alpha)+c*c*cos(alpha)*cos(alpha)); 57 if (t==0.0){ 58 kernel = 1.0; 59 }else{ 60 kernel = 3.0*(sin(t)-t*cos(t))/(t*t*t); 61 } 62 return kernel*kernel; 63 } 64 65 66 /** 67 * Function to evaluate 2D scattering function 68 * @param pars: parameters of the triaxial ellipsoid 69 * @param q: q-value 70 * @param q_x: q_x / q 71 * @param q_y: q_y / q 72 * @return: function value 73 */ 74 static double triaxial_ellipsoid_analytical_2D_scaled(TriaxialEllipsoidParameters *pars, double q, double q_x, double q_y) { 75 double cyl_x, cyl_y, cyl_z, ell_x, ell_y; 76 double q_z; 77 double cos_nu,nu; 78 double alpha, vol, cos_val; 79 double answer; 80 double pi = 4.0*atan(1.0); 81 82 //convert angle degree to radian 83 double theta = pars->axis_theta * pi/180.0; 84 double phi = pars->axis_phi * pi/180.0; 85 double psi = pars->axis_psi * pi/180.0; 86 87 // Cylinder orientation 88 cyl_x = sin(theta) * cos(phi); 89 cyl_y = sin(theta) * sin(phi); 90 cyl_z = cos(theta); 91 92 // q vector 93 q_z = 0.0; 94 95 //dx = 1.0; 96 //dy = 1.0; 97 // Compute the angle btw vector q and the 98 // axis of the cylinder 99 cos_val = cyl_x*q_x + cyl_y*q_y + cyl_z*q_z; 100 101 // The following test should always pass 102 if (fabs(cos_val)>1.0) { 103 printf("cyl_ana_2D: Unexpected error: cos(alpha)>1\n"); 104 return 0; 105 } 106 107 // Note: cos(alpha) = 0 and 1 will get an 108 // undefined value from CylKernel 109 alpha = acos( cos_val ); 110 111 //ellipse orientation: 112 // the elliptical corss section was transformed and projected 113 // into the detector plane already through sin(alpha)and furthermore psi remains as same 114 // on the detector plane. 115 // So, all we need is to calculate the angle (nu) of the minor axis of the ellipse wrt 116 // the wave vector q. 117 118 //x- y- component on the detector plane. 119 ell_x = cos(psi); 120 ell_y = sin(psi); 121 122 // calculate the axis of the ellipse wrt q-coord. 123 cos_nu = ell_x*q_x + ell_y*q_y; 124 nu = acos(cos_nu); 125 126 // Call the IGOR library function to get the kernel 127 answer = triaxial_ellipsoid_kernel(pars, q, alpha, nu); 128 129 // Multiply by contrast^2 130 answer *= (pars->sldEll- pars->sldSolv)*(pars->sldEll- pars->sldSolv); 131 132 //normalize by cylinder volume 133 //NOTE that for this (Fournet) definition of the integral, one must MULTIPLY by Vcyl 134 vol = 4.0* pi/3.0 * pars->semi_axisA * pars->semi_axisB * pars->semi_axisC; 135 answer *= vol; 136 //convert to [cm-1] 137 answer *= 1.0e8; 138 //Scale 139 answer *= pars->scale; 140 141 // add in the background 142 answer += pars->background; 143 144 return answer; 145 } 146 147 /** 148 * Function to evaluate 2D scattering function 149 * @param pars: parameters of the triaxial ellipsoid 150 * @param q: q-value 151 * @return: function value 152 */ 153 static double triaxial_ellipsoid_analytical_2DXY(TriaxialEllipsoidParameters *pars, double qx, double qy) { 154 double q; 155 q = sqrt(qx*qx+qy*qy); 156 return triaxial_ellipsoid_analytical_2D_scaled(pars, q, qx/q, qy/q); 157 } 158 159 34 160 35 161 TriaxialEllipsoidModel :: TriaxialEllipsoidModel() { 36 37 38 39 40 41 42 43 44 45 46 47 48 162 scale = Parameter(1.0); 163 semi_axisA = Parameter(35.0, true); 164 semi_axisA.set_min(0.0); 165 semi_axisB = Parameter(100.0, true); 166 semi_axisB.set_min(0.0); 167 semi_axisC = Parameter(400.0, true); 168 semi_axisC.set_min(0.0); 169 sldEll = Parameter(1.0e-6); 170 sldSolv = Parameter(6.3e-6); 171 background = Parameter(0.0); 172 axis_theta = Parameter(57.325, true); 173 axis_phi = Parameter(57.325, true); 174 axis_psi = Parameter(0.0, true); 49 175 } 50 176 … … 56 182 */ 57 183 double TriaxialEllipsoidModel :: operator()(double q) { 58 59 60 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 184 double dp[7]; 185 186 // Fill parameter array for IGOR library 187 // Add the background after averaging 188 dp[0] = scale(); 189 dp[1] = semi_axisA(); 190 dp[2] = semi_axisB(); 191 dp[3] = semi_axisC(); 192 dp[4] = sldEll(); 193 dp[5] = sldSolv(); 194 dp[6] = 0.0; 195 196 // Get the dispersion points for the semi axis A 197 vector<WeightPoint> weights_semi_axisA; 198 semi_axisA.get_weights(weights_semi_axisA); 199 200 // Get the dispersion points for the semi axis B 201 vector<WeightPoint> weights_semi_axisB; 202 semi_axisB.get_weights(weights_semi_axisB); 203 204 // Get the dispersion points for the semi axis C 205 vector<WeightPoint> weights_semi_axisC; 206 semi_axisC.get_weights(weights_semi_axisC); 207 208 // Perform the computation, with all weight points 209 double sum = 0.0; 210 double norm = 0.0; 211 double vol = 0.0; 212 213 // Loop over semi axis A weight points 214 for(int i=0; i< (int)weights_semi_axisA.size(); i++) { 215 dp[1] = weights_semi_axisA[i].value; 216 217 // Loop over semi axis B weight points 218 for(int j=0; j< (int)weights_semi_axisB.size(); j++) { 219 dp[2] = weights_semi_axisB[j].value; 220 221 // Loop over semi axis C weight points 222 for(int k=0; k< (int)weights_semi_axisC.size(); k++) { 223 dp[3] = weights_semi_axisC[k].value; 224 //Un-normalize by volume 225 sum += weights_semi_axisA[i].weight 226 * weights_semi_axisB[j].weight * weights_semi_axisC[k].weight* TriaxialEllipsoid(dp, q) 227 * weights_semi_axisA[i].value*weights_semi_axisB[j].value*weights_semi_axisC[k].value; 228 //Find average volume 229 vol += weights_semi_axisA[i].weight 230 * weights_semi_axisB[j].weight * weights_semi_axisC[k].weight 231 * weights_semi_axisA[i].value*weights_semi_axisB[j].value*weights_semi_axisC[k].value; 232 233 norm += weights_semi_axisA[i].weight 234 * weights_semi_axisB[j].weight * weights_semi_axisC[k].weight; 235 } 236 } 237 } 238 if (vol != 0.0 && norm != 0.0) { 239 //Re-normalize by avg volume 240 sum = sum/(vol/norm);} 241 242 return sum/norm + background(); 117 243 } 118 244 … … 124 250 */ 125 251 double TriaxialEllipsoidModel :: operator()(double qx, double qy) { 126 127 128 129 130 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 229 230 231 232 233 234 235 236 252 TriaxialEllipsoidParameters dp; 253 // Fill parameter array 254 dp.scale = scale(); 255 dp.semi_axisA = semi_axisA(); 256 dp.semi_axisB = semi_axisB(); 257 dp.semi_axisC = semi_axisC(); 258 dp.sldEll = sldEll(); 259 dp.sldSolv = sldSolv(); 260 dp.background = 0.0; 261 dp.axis_theta = axis_theta(); 262 dp.axis_phi = axis_phi(); 263 dp.axis_psi = axis_psi(); 264 265 // Get the dispersion points for the semi_axis A 266 vector<WeightPoint> weights_semi_axisA; 267 semi_axisA.get_weights(weights_semi_axisA); 268 269 // Get the dispersion points for the semi_axis B 270 vector<WeightPoint> weights_semi_axisB; 271 semi_axisB.get_weights(weights_semi_axisB); 272 273 // Get the dispersion points for the semi_axis C 274 vector<WeightPoint> weights_semi_axisC; 275 semi_axisC.get_weights(weights_semi_axisC); 276 277 // Get angular averaging for theta 278 vector<WeightPoint> weights_theta; 279 axis_theta.get_weights(weights_theta); 280 281 // Get angular averaging for phi 282 vector<WeightPoint> weights_phi; 283 axis_phi.get_weights(weights_phi); 284 285 // Get angular averaging for psi 286 vector<WeightPoint> weights_psi; 287 axis_psi.get_weights(weights_psi); 288 289 // Perform the computation, with all weight points 290 double sum = 0.0; 291 double norm = 0.0; 292 double norm_vol = 0.0; 293 double vol = 0.0; 294 double pi = 4.0*atan(1.0); 295 // Loop over semi axis A weight points 296 for(int i=0; i< (int)weights_semi_axisA.size(); i++) { 297 dp.semi_axisA = weights_semi_axisA[i].value; 298 299 // Loop over semi axis B weight points 300 for(int j=0; j< (int)weights_semi_axisB.size(); j++) { 301 dp.semi_axisB = weights_semi_axisB[j].value; 302 303 // Loop over semi axis C weight points 304 for(int k=0; k < (int)weights_semi_axisC.size(); k++) { 305 dp.semi_axisC = weights_semi_axisC[k].value; 306 307 // Average over theta distribution 308 for(int l=0; l< (int)weights_theta.size(); l++) { 309 dp.axis_theta = weights_theta[l].value; 310 311 // Average over phi distribution 312 for(int m=0; m <(int)weights_phi.size(); m++) { 313 dp.axis_phi = weights_phi[m].value; 314 // Average over psi distribution 315 for(int n=0; n <(int)weights_psi.size(); n++) { 316 dp.axis_psi = weights_psi[n].value; 317 //Un-normalize by volume 318 double _ptvalue = weights_semi_axisA[i].weight 319 * weights_semi_axisB[j].weight 320 * weights_semi_axisC[k].weight 321 * weights_theta[l].weight 322 * weights_phi[m].weight 323 * weights_psi[n].weight 324 * triaxial_ellipsoid_analytical_2DXY(&dp, qx, qy) 325 * weights_semi_axisA[i].value*weights_semi_axisB[j].value*weights_semi_axisC[k].value; 326 if (weights_theta.size()>1) { 327 _ptvalue *= fabs(sin(weights_theta[k].value*pi/180.0)); 328 } 329 sum += _ptvalue; 330 //Find average volume 331 vol += weights_semi_axisA[i].weight 332 * weights_semi_axisB[j].weight 333 * weights_semi_axisC[k].weight 334 * weights_semi_axisA[i].value*weights_semi_axisB[j].value*weights_semi_axisC[k].value; 335 //Find norm for volume 336 norm_vol += weights_semi_axisA[i].weight 337 * weights_semi_axisB[j].weight 338 * weights_semi_axisC[k].weight; 339 340 norm += weights_semi_axisA[i].weight 341 * weights_semi_axisB[j].weight 342 * weights_semi_axisC[k].weight 343 * weights_theta[l].weight 344 * weights_phi[m].weight 345 * weights_psi[n].weight; 346 } 347 } 348 349 } 350 } 351 } 352 } 353 // Averaging in theta needs an extra normalization 354 // factor to account for the sin(theta) term in the 355 // integration (see documentation). 356 if (weights_theta.size()>1) norm = norm / asin(1.0); 357 358 if (vol != 0.0 && norm_vol != 0.0) { 359 //Re-normalize by avg volume 360 sum = sum/(vol/norm_vol);} 361 362 return sum/norm + background(); 237 363 } 238 364 … … 245 371 */ 246 372 double TriaxialEllipsoidModel :: evaluate_rphi(double q, double phi) { 247 248 249 373 double qx = q*cos(phi); 374 double qy = q*sin(phi); 375 return (*this).operator()(qx, qy); 250 376 } 251 377 /** … … 254 380 */ 255 381 double TriaxialEllipsoidModel :: calculate_ER() { 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 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 } 382 TriaxialEllipsoidParameters dp; 383 384 dp.semi_axisA = semi_axisA(); 385 dp.semi_axisB = semi_axisB(); 386 //polar axis C 387 dp.semi_axisC = semi_axisC(); 388 389 double rad_out = 0.0; 390 //Surface average radius at the equat. cross section. 391 double suf_rad = sqrt(dp.semi_axisA * dp.semi_axisB); 392 393 // Perform the computation, with all weight points 394 double sum = 0.0; 395 double norm = 0.0; 396 397 // Get the dispersion points for the semi_axis A 398 vector<WeightPoint> weights_semi_axisA; 399 semi_axisA.get_weights(weights_semi_axisA); 400 401 // Get the dispersion points for the semi_axis B 402 vector<WeightPoint> weights_semi_axisB; 403 semi_axisB.get_weights(weights_semi_axisB); 404 405 // Get the dispersion points for the semi_axis C 406 vector<WeightPoint> weights_semi_axisC; 407 semi_axisC.get_weights(weights_semi_axisC); 408 409 // Loop over semi axis A weight points 410 for(int i=0; i< (int)weights_semi_axisA.size(); i++) { 411 dp.semi_axisA = weights_semi_axisA[i].value; 412 413 // Loop over semi axis B weight points 414 for(int j=0; j< (int)weights_semi_axisB.size(); j++) { 415 dp.semi_axisB = weights_semi_axisB[j].value; 416 417 // Loop over semi axis C weight points 418 for(int k=0; k < (int)weights_semi_axisC.size(); k++) { 419 dp.semi_axisC = weights_semi_axisC[k].value; 420 421 //Calculate surface averaged radius 422 suf_rad = sqrt(dp.semi_axisA * dp.semi_axisB); 423 424 //Sum 425 sum += weights_semi_axisA[i].weight 426 * weights_semi_axisB[j].weight 427 * weights_semi_axisC[k].weight * DiamEllip(dp.semi_axisC, suf_rad)/2.0; 428 //Norm 429 norm += weights_semi_axisA[i].weight* weights_semi_axisB[j].weight 430 * weights_semi_axisC[k].weight; 431 } 432 } 433 } 434 if (norm != 0){ 435 //return the averaged value 436 rad_out = sum/norm;} 437 else{ 438 //return normal value 439 rad_out = DiamEllip(dp.semi_axisC, suf_rad)/2.0;} 440 441 return rad_out; 442 } -
sansmodels/src/c_models/vesicle.cpp
r67424cd r82c11d3 21 21 22 22 #include <math.h> 23 #include "models.hh"24 23 #include "parameters.hh" 25 24 #include <stdio.h> 26 25 using namespace std; 26 #include "vesicle.h" 27 27 28 28 extern "C" { 29 #include "libSphere.h" 30 #include "vesicle.h" 29 #include "libSphere.h" 31 30 } 32 31 32 typedef struct { 33 double scale; 34 double radius; 35 double thickness; 36 double core_sld; 37 double shell_sld; 38 double background; 39 } VesicleParameters; 40 33 41 VesicleModel :: VesicleModel() { 34 35 36 37 38 39 40 41 42 scale = Parameter(1.0); 43 radius = Parameter(100.0, true); 44 radius.set_min(0.0); 45 thickness = Parameter(30.0, true); 46 thickness.set_min(0.0); 47 core_sld = Parameter(6.36e-6); 48 shell_sld = Parameter(5.0e-7); 49 background = Parameter(0.0); 42 50 } 43 51 … … 49 57 */ 50 58 double VesicleModel :: operator()(double q) { 51 59 double dp[6]; 52 60 53 54 55 56 57 58 59 60 61 // Fill parameter array for IGOR library 62 // Add the background after averaging 63 dp[0] = scale(); 64 dp[1] = radius(); 65 dp[2] = thickness(); 66 dp[3] = core_sld(); 67 dp[4] = shell_sld(); 68 dp[5] = 0.0; 61 69 62 70 63 64 65 66 67 68 71 // Get the dispersion points for the core radius 72 vector<WeightPoint> weights_radius; 73 radius.get_weights(weights_radius); 74 // Get the dispersion points for the thickness 75 vector<WeightPoint> weights_thickness; 76 thickness.get_weights(weights_thickness); 69 77 70 71 72 73 78 // Perform the computation, with all weight points 79 double sum = 0.0; 80 double norm = 0.0; 81 double vol = 0.0; 74 82 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 83 // Loop over radius weight points 84 for(int i=0; i< (int)weights_radius.size(); i++) { 85 dp[1] = weights_radius[i].value; 86 for(int j=0; j< (int)weights_thickness.size(); j++) { 87 dp[2] = weights_thickness[j].value; 88 sum += weights_radius[i].weight 89 * weights_thickness[j].weight * VesicleForm(dp, q) 90 *(pow(weights_radius[i].value+weights_thickness[j].value,3)-pow(weights_radius[i].value,3)); 91 //Find average volume 92 vol += weights_radius[i].weight * weights_thickness[j].weight 93 *(pow(weights_radius[i].value+weights_thickness[j].value,3)-pow(weights_radius[i].value,3)); 94 norm += weights_radius[i].weight * weights_thickness[j].weight; 95 } 96 } 97 if (vol != 0.0 && norm != 0.0) { 98 //Re-normalize by avg volume 99 sum = sum/(vol/norm);} 92 100 93 101 return sum/norm + background(); 94 102 } 95 103 … … 101 109 */ 102 110 double VesicleModel :: operator()(double qx, double qy) { 103 104 111 double q = sqrt(qx*qx + qy*qy); 112 return (*this).operator()(q); 105 113 } 106 114 … … 113 121 */ 114 122 double VesicleModel :: evaluate_rphi(double q, double phi) { 115 123 return (*this).operator()(q); 116 124 } 117 125 /** … … 120 128 */ 121 129 double VesicleModel :: calculate_ER() { 122 130 VesicleParameters dp; 123 131 124 125 132 dp.radius = radius(); 133 dp.thickness = thickness(); 126 134 127 135 double rad_out = 0.0; 128 136 129 130 131 137 // Perform the computation, with all weight points 138 double sum = 0.0; 139 double norm = 0.0; 132 140 133 141 134 135 136 142 // Get the dispersion points for the major shell 143 vector<WeightPoint> weights_thickness; 144 thickness.get_weights(weights_thickness); 137 145 138 139 140 146 // Get the dispersion points for the minor shell 147 vector<WeightPoint> weights_radius ; 148 radius.get_weights(weights_radius); 141 149 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 150 // Loop over major shell weight points 151 for(int j=0; j< (int)weights_thickness.size(); j++) { 152 dp.thickness = weights_thickness[j].value; 153 for(int k=0; k< (int)weights_radius.size(); k++) { 154 dp.radius = weights_radius[k].value; 155 sum += weights_thickness[j].weight 156 * weights_radius[k].weight*(dp.radius+dp.thickness); 157 norm += weights_thickness[j].weight* weights_radius[k].weight; 158 } 159 } 160 if (norm != 0){ 161 //return the averaged value 162 rad_out = sum/norm;} 163 else{ 164 //return normal value 165 rad_out = (dp.radius+dp.thickness);} 158 166 159 167 return rad_out; 160 168 }
Note: See TracChangeset
for help on using the changeset viewer.