Changeset 82c11d3 in sasview for sansmodels/src/c_models


Ignore:
Timestamp:
Jan 5, 2012 6:24:51 PM (13 years ago)
Author:
Mathieu Doucet <doucetm@…>
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
Message:

refactored bunch of models

Location:
sansmodels/src/c_models
Files:
1 added
1 deleted
24 edited

Legend:

Unmodified
Added
Removed
  • sansmodels/src/c_models/binaryHS.cpp

    r67424cd r82c11d3  
    2121 
    2222#include <math.h> 
    23 #include "models.hh" 
    2423#include "parameters.hh" 
    2524#include <stdio.h> 
    2625using namespace std; 
     26#include "binaryHS.h" 
    2727 
    2828extern "C" { 
    29         #include "libSphere.h" 
    30         #include "binaryHS.h" 
     29#include "libSphere.h" 
    3130} 
    3231 
    3332BinaryHSModel :: BinaryHSModel() { 
    3433 
    35         l_radius     = Parameter(160.0, true); 
    36         l_radius.set_min(0.0); 
    37         s_radius    = Parameter(25.0, true); 
    38         s_radius.set_min(0.0); 
    39         vol_frac_ls  = Parameter(0.2); 
    40         vol_frac_ss  = Parameter(0.1); 
    41         ls_sld      = Parameter(3.5e-6); 
    42         ss_sld     = Parameter(5e-7); 
    43         solvent_sld   = Parameter(6.36e-6); 
    44         background = Parameter(0.0); 
     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); 
    4544} 
    4645 
     
    5251 */ 
    5352double BinaryHSModel :: operator()(double q) { 
    54         double dp[8]; 
     53  double dp[8]; 
    5554 
    56         // Fill parameter array for IGOR library 
    57         // Add the background after averaging 
    58         dp[0] = l_radius(); 
    59         dp[1] = s_radius(); 
    60         dp[2] = vol_frac_ls(); 
    61         dp[3] = vol_frac_ss(); 
    62         dp[4] = ls_sld(); 
    63         dp[5] = ss_sld(); 
    64         dp[6] = solvent_sld(); 
    65         dp[7] = 0.0; 
     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; 
    6665 
    6766 
    68         // Get the dispersion points for the large radius 
    69         vector<WeightPoint> weights_l_radius; 
    70         l_radius.get_weights(weights_l_radius); 
     67  // Get the dispersion points for the large radius 
     68  vector<WeightPoint> weights_l_radius; 
     69  l_radius.get_weights(weights_l_radius); 
    7170 
    72         // Get the dispersion points for the small radius 
    73         vector<WeightPoint> weights_s_radius; 
    74         s_radius.get_weights(weights_s_radius); 
     71  // Get the dispersion points for the small radius 
     72  vector<WeightPoint> weights_s_radius; 
     73  s_radius.get_weights(weights_s_radius); 
    7574 
    76         // Perform the computation, with all weight points 
    77         double sum = 0.0; 
    78         double norm = 0.0; 
     75  // Perform the computation, with all weight points 
     76  double sum = 0.0; 
     77  double norm = 0.0; 
    7978 
    80         // Loop over larger radius weight points 
    81         for(int i=0; i< (int)weights_l_radius.size(); i++) { 
    82                 dp[0] = weights_l_radius[i].value; 
     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; 
    8382 
    84                 // Loop over small radius weight points 
    85                 for(int j=0; j< (int)weights_s_radius.size(); j++) { 
    86                         dp[1] = weights_s_radius[j].value; 
     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; 
    8786 
    8887 
    89                         sum += weights_l_radius[i].weight *weights_s_radius[j].weight * BinaryHS(dp, q); 
    90                         norm += weights_l_radius[i].weight *weights_s_radius[j].weight; 
    91                 } 
    92         } 
    93         return sum/norm + background(); 
     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(); 
    9493} 
    9594 
     
    101100 */ 
    102101double BinaryHSModel :: operator()(double qx, double qy) { 
    103         double q = sqrt(qx*qx + qy*qy); 
    104         return (*this).operator()(q); 
     102  double q = sqrt(qx*qx + qy*qy); 
     103  return (*this).operator()(q); 
    105104} 
    106105 
     
    113112 */ 
    114113double BinaryHSModel :: evaluate_rphi(double q, double phi) { 
    115         return (*this).operator()(q); 
     114  return (*this).operator()(q); 
    116115} 
    117116 
     
    121120 */ 
    122121double BinaryHSModel :: calculate_ER() { 
    123         //NOT implemented yet!!! 
    124         return 0.0; 
     122  //NOT implemented yet!!! 
     123  return 0.0; 
    125124} 
    126125 
  • sansmodels/src/c_models/binaryHS_PSF11.cpp

    r67424cd r82c11d3  
    2121 
    2222#include <math.h> 
    23 #include "models.hh" 
    2423#include "parameters.hh" 
    2524#include <stdio.h> 
     
    2928        #include "libSphere.h" 
    3029} 
     30 
     31class BinaryHSPSF11Model{ 
     32public: 
     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}; 
    3152 
    3253BinaryHSPSF11Model :: BinaryHSPSF11Model() { 
  • sansmodels/src/c_models/c_models.cpp

    r67424cd r82c11d3  
    6868        void addDisperser(PyObject *module); 
    6969        void addCGaussian(PyObject *module); 
    70         void addCLorentzian(PyObject *module); 
    7170        void addCLogNormal(PyObject *module); 
    7271        void addCSchulz(PyObject *module); 
    7372} 
     73void addCLorentzian(PyObject *module); 
    7474 
    7575/** 
  • sansmodels/src/c_models/coreshellcylinder.cpp

    r011e0e4 r82c11d3  
    2727 
    2828extern "C" { 
    29         #include "libCylinder.h" 
    30         #include "libStructureFactor.h" 
     29#include "libCylinder.h" 
     30#include "libStructureFactor.h" 
    3131} 
    3232 
     
    6363  double phi = pars->axis_phi * pi/180.0; 
    6464 
    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     } 
     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  } 
    8282 
    8383  alpha = acos( cos_val ); 
     
    8585  // Call the IGOR library function to get the kernel 
    8686  answer = CoreShellCylKernel(q, pars->radius, pars->thickness, 
    87                 pars->core_sld,pars->shell_sld, 
    88                 pars->solvent_sld, pars->length/2.0, alpha) / fabs(sin(alpha)); 
     87      pars->core_sld,pars->shell_sld, 
     88      pars->solvent_sld, pars->length/2.0, alpha) / fabs(sin(alpha)); 
    8989 
    9090  //normalize by cylinder volume 
    9191  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); 
    9494  answer /= vol; 
    9595 
     
    115115  double q; 
    116116  q = sqrt(qx*qx+qy*qy); 
    117     return core_shell_cylinder_analytical_2D_scaled(pars, q, qx/q, qy/q); 
     117  return core_shell_cylinder_analytical_2D_scaled(pars, q, qx/q, qy/q); 
    118118} 
    119119 
    120120 
    121121CoreShellCylinderModel :: CoreShellCylinderModel() { 
    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); 
     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); 
    135135} 
    136136 
     
    142142 */ 
    143143double CoreShellCylinderModel :: operator()(double q) { 
    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(); 
     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(); 
    208208} 
    209209 
     
    215215 */ 
    216216double CoreShellCylinderModel :: operator()(double qx, double qy) { 
    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(); 
     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(); 
    323323} 
    324324 
     
    331331 */ 
    332332double CoreShellCylinderModel :: evaluate_rphi(double q, double phi) { 
    333         double qx = q*cos(phi); 
    334         double qy = q*sin(phi); 
    335         return (*this).operator()(qx, qy); 
     333  double qx = q*cos(phi); 
     334  double qy = q*sin(phi); 
     335  return (*this).operator()(qx, qy); 
    336336} 
    337337/** 
     
    340340 */ 
    341341double CoreShellCylinderModel :: calculate_ER() { 
    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 } 
     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  
    2727 
    2828extern "C" { 
    29         #include "libCylinder.h" 
    30         #include "libStructureFactor.h" 
     29#include "libCylinder.h" 
     30#include "libStructureFactor.h" 
    3131} 
    3232 
     
    6060  double phi = pars->axis_phi * pi/180.0; 
    6161 
    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 
     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 
    8181  alpha = acos( cos_val ); 
    8282 
     
    8888 
    8989  //normalize by cylinder volume 
    90     vol = 4.0/3.0 * acos(-1.0) * pars->radius_b * pars->radius_b * pars->radius_a; 
     90  vol = 4.0/3.0 * acos(-1.0) * pars->radius_b * pars->radius_b * pars->radius_a; 
    9191  answer *= vol; 
    9292 
     
    112112  double q; 
    113113  q = sqrt(qx*qx+qy*qy); 
    114     return ellipsoid_analytical_2D_scaled(pars, q, qx/q, qy/q); 
     114  return ellipsoid_analytical_2D_scaled(pars, q, qx/q, qy/q); 
    115115} 
    116116 
    117117EllipsoidModel :: EllipsoidModel() { 
    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); 
     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); 
    128128} 
    129129 
     
    135135 */ 
    136136double EllipsoidModel :: operator()(double q) { 
    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(); 
     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(); 
    188188} 
    189189 
     
    195195 */ 
    196196double EllipsoidModel :: operator()(double qx, double qy) { 
    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(); 
     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(); 
    284284} 
    285285 
     
    292292 */ 
    293293double EllipsoidModel :: evaluate_rphi(double q, double phi) { 
    294         double qx = q*cos(phi); 
    295         double qy = q*sin(phi); 
    296         return (*this).operator()(qx, qy); 
     294  double qx = q*cos(phi); 
     295  double qy = q*sin(phi); 
     296  return (*this).operator()(qx, qy); 
    297297} 
    298298 
     
    302302 */ 
    303303double EllipsoidModel :: calculate_ER() { 
    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 } 
     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  
    1818 *   sansmodels/src/libigor 
    1919 * 
    20  *      TODO: refactor so that we pull in the old sansmodels.c_extensions 
    2120 */ 
    2221 
    2322#include <math.h> 
    24 #include "models.hh" 
    2523#include "parameters.hh" 
    2624#include <stdio.h> 
     25#include <stdlib.h> 
    2726using namespace std; 
     27#include "elliptical_cylinder.h" 
    2828 
    2929extern "C" { 
    30         #include "libCylinder.h" 
    31         #include "libStructureFactor.h" 
    32         #include "elliptical_cylinder.h" 
     30#include "libCylinder.h" 
     31#include "libStructureFactor.h" 
     32} 
     33 
     34typedef 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 
     48static 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 */ 
     84static 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 */ 
     169static 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); 
    33173} 
    34174 
    35175EllipticalCylinderModel :: EllipticalCylinderModel() { 
    36         scale      = Parameter(1.0); 
    37         r_minor    = Parameter(20.0, true); 
    38         r_minor.set_min(0.0); 
    39         r_ratio    = Parameter(1.5, true); 
    40         r_ratio.set_min(0.0); 
    41         length     = Parameter(400.0, true); 
    42         length.set_min(0.0); 
    43         sldCyl   = Parameter(4.e-6); 
    44         sldSolv   = Parameter(1.e-6); 
    45         background = Parameter(0.0); 
    46         cyl_theta  = Parameter(57.325, true); 
    47         cyl_phi    = Parameter(0.0, true); 
    48         cyl_psi    = Parameter(0.0, true); 
     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); 
    49189} 
    50190 
     
    56196 */ 
    57197double EllipticalCylinderModel :: operator()(double q) { 
    58         double dp[7]; 
    59  
    60         dp[0] = scale(); 
    61         dp[1] = r_minor(); 
    62         dp[2] = r_ratio(); 
    63         dp[3] = length(); 
    64         dp[4] = sldCyl(); 
    65         dp[5] = sldSolv(); 
    66         dp[6] = 0.0; 
    67  
    68         // Get the dispersion points for the r_minor 
    69         vector<WeightPoint> weights_rad; 
    70         r_minor.get_weights(weights_rad); 
    71  
    72         // Get the dispersion points for the r_ratio 
    73         vector<WeightPoint> weights_rat; 
    74         r_ratio.get_weights(weights_rat); 
    75  
    76         // Get the dispersion points for the length 
    77         vector<WeightPoint> weights_len; 
    78         length.get_weights(weights_len); 
    79  
    80         // Perform the computation, with all weight points 
    81         double sum = 0.0; 
    82         double norm = 0.0; 
    83         double vol = 0.0; 
    84  
    85         // Loop over r_minor weight points 
    86         for(size_t i=0; i<weights_rad.size(); i++) { 
    87                 dp[1] = weights_rad[i].value; 
    88  
    89                 // Loop over r_ratio weight points 
    90                 for(size_t j=0; j<weights_rat.size(); j++) { 
    91                         dp[2] = weights_rat[j].value; 
    92  
    93                         // Loop over length weight points 
    94                         for(size_t k=0; k<weights_len.size(); k++) { 
    95                                 dp[3] = weights_len[k].value; 
    96                                 //Un-normalize  by volume 
    97                                 sum += weights_rad[i].weight 
    98                                         * weights_len[k].weight 
    99                                         * weights_rat[j].weight 
    100                                         * EllipCyl20(dp, q) 
    101                                         * pow(weights_rad[i].value,2) * weights_rat[j].value 
    102                                         * weights_len[k].value; 
    103                                 //Find average volume 
    104                                 vol += weights_rad[i].weight 
    105                                         * weights_len[k].weight 
    106                                         * weights_rat[j].weight 
    107                                         * pow(weights_rad[i].value,2) * weights_rat[j].value 
    108                                         * weights_len[k].value; 
    109                                 norm += weights_rad[i].weight 
    110                                         * weights_len[k].weight 
    111                                         * weights_rat[j].weight; 
    112                         } 
    113                 } 
    114         } 
    115  
    116         if (vol != 0.0 && norm != 0.0) { 
    117                 //Re-normalize by avg volume 
    118                 sum = sum/(vol/norm);} 
    119  
    120         return sum/norm + background(); 
     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(); 
    121261} 
    122262 
     
    128268 */ 
    129269double EllipticalCylinderModel :: operator()(double qx, double qy) { 
    130         EllipticalCylinderParameters dp; 
    131         // Fill parameter array 
    132         dp.scale      = scale(); 
    133         dp.r_minor    = r_minor(); 
    134         dp.r_ratio    = r_ratio(); 
    135         dp.length     = length(); 
    136         dp.sldCyl   = sldCyl(); 
    137         dp.sldSolv   = sldSolv(); 
    138         dp.background = 0.0; 
    139         dp.cyl_theta  = cyl_theta(); 
    140         dp.cyl_phi    = cyl_phi(); 
    141         dp.cyl_psi    = cyl_psi(); 
    142  
    143         // Get the dispersion points for the r_minor 
    144         vector<WeightPoint> weights_rad; 
    145         r_minor.get_weights(weights_rad); 
    146  
    147         // Get the dispersion points for the r_ratio 
    148         vector<WeightPoint> weights_rat; 
    149         r_ratio.get_weights(weights_rat); 
    150  
    151         // Get the dispersion points for the length 
    152         vector<WeightPoint> weights_len; 
    153         length.get_weights(weights_len); 
    154  
    155         // Get angular averaging for theta 
    156         vector<WeightPoint> weights_theta; 
    157         cyl_theta.get_weights(weights_theta); 
    158  
    159         // Get angular averaging for phi 
    160         vector<WeightPoint> weights_phi; 
    161         cyl_phi.get_weights(weights_phi); 
    162  
    163         // Get angular averaging for psi 
    164         vector<WeightPoint> weights_psi; 
    165         cyl_psi.get_weights(weights_psi); 
    166  
    167         // Perform the computation, with all weight points 
    168         double sum = 0.0; 
    169         double norm = 0.0; 
    170         double norm_vol = 0.0; 
    171         double vol = 0.0; 
    172         double pi = 4.0*atan(1.0); 
    173         // Loop over minor radius weight points 
    174         for(size_t i=0; i<weights_rad.size(); i++) { 
    175                 dp.r_minor = weights_rad[i].value; 
    176  
    177  
    178                 // Loop over length weight points 
    179                 for(size_t j=0; j<weights_len.size(); j++) { 
    180                         dp.length = weights_len[j].value; 
    181  
    182                         // Loop over r_ration weight points 
    183                         for(size_t m=0; m<weights_rat.size(); m++) { 
    184                                 dp.r_ratio = weights_rat[m].value; 
    185  
    186                         // Average over theta distribution 
    187                         for(size_t k=0; k<weights_theta.size(); k++) { 
    188                                 dp.cyl_theta = weights_theta[k].value; 
    189  
    190                                 // Average over phi distribution 
    191                                 for(size_t l=0; l<weights_phi.size(); l++) { 
    192                                         dp.cyl_phi = weights_phi[l].value; 
    193  
    194                                 // Average over phi distribution 
    195                                 for(size_t o=0; o<weights_psi.size(); o++) { 
    196                                         dp.cyl_psi = weights_psi[o].value; 
    197                                         //Un-normalize by volume 
    198                                         double _ptvalue = weights_rad[i].weight 
    199                                                 * weights_len[j].weight 
    200                                                 * weights_rat[m].weight 
    201                                                 * weights_theta[k].weight 
    202                                                 * weights_phi[l].weight 
    203                                                 * weights_psi[o].weight 
    204                                                 * elliptical_cylinder_analytical_2DXY(&dp, qx, qy) 
    205                                                 * pow(weights_rad[i].value,2) 
    206                                                 * weights_len[j].value 
    207                                                 * weights_rat[m].value; 
    208                                         if (weights_theta.size()>1) { 
    209                                                 _ptvalue *= fabs(sin(weights_theta[k].value*pi/180.0)); 
    210                                         } 
    211                                         sum += _ptvalue; 
    212                                         //Find average volume 
    213                                         vol += weights_rad[i].weight 
    214                                                 * weights_len[j].weight 
    215                                                 * weights_rat[m].weight 
    216                                                 * pow(weights_rad[i].value,2) 
    217                                                 * weights_len[j].value 
    218                                                 * weights_rat[m].value; 
    219                                         //Find norm for volume 
    220                                         norm_vol += weights_rad[i].weight 
    221                                                 * weights_len[j].weight 
    222                                                 * weights_rat[m].weight; 
    223  
    224                                         norm += weights_rad[i].weight 
    225                                                 * weights_len[j].weight 
    226                                                 * weights_rat[m].weight 
    227                                                 * weights_theta[k].weight 
    228                                                 * weights_phi[l].weight 
    229                                                 * weights_psi[o].weight; 
    230  
    231                                 } 
    232                                 } 
    233                         } 
    234                         } 
    235                 } 
    236         } 
    237         // Averaging in theta needs an extra normalization 
    238         // factor to account for the sin(theta) term in the 
    239         // integration (see documentation). 
    240         if (weights_theta.size()>1) norm = norm / asin(1.0); 
    241  
    242         if (vol != 0.0 && norm_vol != 0.0) { 
    243                 //Re-normalize by avg volume 
    244                 sum = sum/(vol/norm_vol);} 
    245  
    246         return sum/norm + background(); 
     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(); 
    247387 
    248388} 
     
    256396 */ 
    257397double EllipticalCylinderModel :: evaluate_rphi(double q, double phi) { 
    258         double qx = q*cos(phi); 
    259         double qy = q*sin(phi); 
    260         return (*this).operator()(qx, qy); 
     398  double qx = q*cos(phi); 
     399  double qy = q*sin(phi); 
     400  return (*this).operator()(qx, qy); 
    261401} 
    262402/** 
     
    265405 */ 
    266406double EllipticalCylinderModel :: calculate_ER() { 
    267         EllipticalCylinderParameters dp; 
    268         dp.r_minor    = r_minor(); 
    269         dp.r_ratio    = r_ratio(); 
    270         dp.length     = length(); 
    271         double rad_out = 0.0; 
    272         double suf_rad = sqrt(dp.r_minor*dp.r_minor*dp.r_ratio); 
    273  
    274         // Perform the computation, with all weight points 
    275         double sum = 0.0; 
    276         double norm = 0.0; 
    277  
    278         // Get the dispersion points for the r_minor 
    279         vector<WeightPoint> weights_rad; 
    280         r_minor.get_weights(weights_rad); 
    281  
    282         // Get the dispersion points for the r_ratio 
    283         vector<WeightPoint> weights_rat; 
    284         r_ratio.get_weights(weights_rat); 
    285  
    286         // Get the dispersion points for the length 
    287         vector<WeightPoint> weights_len; 
    288         length.get_weights(weights_len); 
    289  
    290         // Loop over minor radius weight points 
    291         for(size_t i=0; i<weights_rad.size(); i++) { 
    292                 dp.r_minor = weights_rad[i].value; 
    293  
    294                 // Loop over length weight points 
    295                 for(size_t j=0; j<weights_len.size(); j++) { 
    296                         dp.length = weights_len[j].value; 
    297  
    298                         // Loop over r_ration weight points 
    299                         for(size_t m=0; m<weights_rat.size(); m++) { 
    300                                 dp.r_ratio = weights_rat[m].value; 
    301                                 //Calculate surface averaged radius 
    302                                 suf_rad = sqrt(dp.r_minor * dp.r_minor * dp.r_ratio); 
    303  
    304                                 //Note: output of "DiamCyl(dp.length,dp.radius)" is DIAMETER. 
    305                                 sum +=weights_rad[i].weight *weights_len[j].weight 
    306                                         * weights_rat[m].weight*DiamCyl(dp.length, suf_rad)/2.0; 
    307                                 norm += weights_rad[i].weight *weights_len[j].weight* weights_rat[m].weight; 
    308                         } 
    309                 } 
    310         } 
    311         if (norm != 0){ 
    312                 //return the averaged value 
    313                 rad_out =  sum/norm;} 
    314         else{ 
    315                 //return normal value 
    316                 //Note: output of "DiamCyl(dp.length,dp.radius)" is DIAMETER. 
    317                 rad_out = DiamCyl(dp.length, suf_rad)/2.0;} 
    318  
    319         return rad_out; 
    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  
    2121 
    2222#include <math.h> 
    23 #include "models.hh" 
    2423#include "parameters.hh" 
    2524#include <stdio.h> 
    2625using namespace std; 
     26#include "flexcyl_ellipX.h" 
    2727 
    2828extern "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 
     33typedef 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; 
    3343 
    3444FlexCylEllipXModel :: FlexCylEllipXModel() { 
    35         scale      = Parameter(1.0); 
    36         length     = Parameter(1000.0, true); 
    37         length.set_min(0.0); 
    38         kuhn_length = Parameter(100.0, true); 
    39         kuhn_length.set_min(0.0); 
    40         radius  = Parameter(20.0, true); 
    41         radius.set_min(0.0); 
    42         axis_ratio = Parameter(1.5); 
    43         axis_ratio.set_min(0.0); 
    44         sldCyl   = Parameter(1.0e-6); 
    45         sldSolv   = Parameter(6.3e-6); 
    46         background = Parameter(0.0001); 
     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); 
    4757} 
    4858 
     
    5464 */ 
    5565double FlexCylEllipXModel :: operator()(double q) { 
    56         double dp[8]; 
    57  
    58         // Fill parameter array for IGOR library 
    59         // Add the background after averaging 
    60         dp[0] = scale(); 
    61         dp[1] = length(); 
    62         dp[2] = kuhn_length(); 
    63         dp[3] = radius(); 
    64         dp[4] = axis_ratio(); 
    65         dp[5] = sldCyl(); 
    66         dp[6] = sldSolv(); 
    67         dp[7] = 0.0; 
    68  
    69         // Get the dispersion points for the length 
    70         vector<WeightPoint> weights_len; 
    71         length.get_weights(weights_len); 
    72  
    73         // Get the dispersion points for the kuhn_length 
    74         vector<WeightPoint> weights_kuhn; 
    75         kuhn_length.get_weights(weights_kuhn); 
    76  
    77         // Get the dispersion points for the radius 
    78         vector<WeightPoint> weights_rad; 
    79         radius.get_weights(weights_rad); 
    80  
    81         // Get the dispersion points for the axis_ratio 
    82         vector<WeightPoint> weights_ratio; 
    83         axis_ratio.get_weights(weights_ratio); 
    84  
    85         // Perform the computation, with all weight points 
    86         double sum = 0.0; 
    87         double norm = 0.0; 
    88         double vol = 0.0; 
    89  
    90         // Loop over length weight points 
    91         for(int i=0; i< (int)weights_len.size(); i++) { 
    92                 dp[1] = weights_len[i].value; 
    93  
    94                 // Loop over kuhn_length weight points 
    95                 for(int j=0; j< (int)weights_kuhn.size(); j++) { 
    96                         dp[2] = weights_kuhn[j].value; 
    97  
    98                         // Loop over radius weight points 
    99                         for(int k=0; k< (int)weights_rad.size(); k++) { 
    100                                 dp[3] = weights_rad[k].value; 
    101                                 // Loop over axis_ratio weight points 
    102                                 for(int l=0; l< (int)weights_ratio.size(); l++) { 
    103                                         dp[4] = weights_ratio[l].value; 
    104  
    105                                         //Un-normalize by volume 
    106                                         sum += weights_len[i].weight * weights_kuhn[j].weight*weights_rad[k].weight 
    107                                                 * weights_ratio[l].weight * FlexCyl_Ellip(dp, q) 
    108                                                 * (pow(weights_rad[k].value,2.0) * weights_ratio[l].value * weights_len[i].value); 
    109                                         //Find weighted volume 
    110                                         vol += weights_rad[k].weight * weights_kuhn[j].weight 
    111                                                 * weights_len[i].weight * weights_ratio[l].weight 
    112                                                 *pow(weights_rad[k].value,2.0)* weights_ratio[l].weight*weights_len[i].value; 
    113                                         norm += weights_len[i].weight * weights_kuhn[j].weight 
    114                                                 *weights_rad[k].weight* weights_ratio[l].weight; 
    115                                 } 
    116                         } 
    117                 } 
    118         } 
    119         if (vol != 0.0 && norm != 0.0) { 
    120                 //Re-normalize by avg volume 
    121                 sum = sum/(vol/norm);} 
    122  
    123         return sum/norm + background(); 
     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(); 
    124134} 
    125135 
     
    131141 */ 
    132142double FlexCylEllipXModel :: operator()(double qx, double qy) { 
    133         double q = sqrt(qx*qx + qy*qy); 
    134         return (*this).operator()(q); 
     143  double q = sqrt(qx*qx + qy*qy); 
     144  return (*this).operator()(q); 
    135145} 
    136146 
     
    143153 */ 
    144154double FlexCylEllipXModel :: evaluate_rphi(double q, double phi) { 
    145         //double qx = q*cos(phi); 
    146         //double qy = q*sin(phi); 
    147         return (*this).operator()(q); 
     155  //double qx = q*cos(phi); 
     156  //double qy = q*sin(phi); 
     157  return (*this).operator()(q); 
    148158} 
    149159/** 
     
    152162 */ 
    153163double FlexCylEllipXModel :: calculate_ER() { 
    154         FlexCylEXParameters dp; 
    155  
    156         dp.radius  = radius(); 
    157         dp.length     = length(); 
    158         dp.axis_ratio  = axis_ratio(); 
    159  
    160         double rad_out = 0.0; 
    161         double suf_rad = sqrt(dp.radius*dp.radius*dp.axis_ratio ); 
    162         // Perform the computation, with all weight points 
    163         double sum = 0.0; 
    164         double norm = 0.0; 
    165  
    166         // Get the dispersion points for the total length 
    167         vector<WeightPoint> weights_length; 
    168         length.get_weights(weights_length); 
    169  
    170         // Get the dispersion points for minor radius 
    171         vector<WeightPoint> weights_radius ; 
    172         radius.get_weights(weights_radius); 
    173  
    174         // Get the dispersion points for axis ratio = major_radius/minor_radius 
    175         vector<WeightPoint> weights_ratio ; 
    176         axis_ratio.get_weights(weights_ratio); 
    177  
    178         // Loop over major shell weight points 
    179         for(int i=0; i< (int)weights_length.size(); i++) { 
    180                 dp.length = weights_length[i].value; 
    181                 for(int k=0; k< (int)weights_radius.size(); k++) { 
    182                         dp.radius = weights_radius[k].value; 
    183                         // Loop over axis_ratio weight points 
    184                         for(int l=0; l< (int)weights_ratio.size(); l++) { 
    185                                 dp.axis_ratio = weights_ratio[l].value; 
    186                                 suf_rad = sqrt(dp.radius  * dp.radius  * dp.axis_ratio); 
    187                                 //Note: output of "DiamCyl(dp.length,dp.radius)" is DIAMETER. 
    188                                 sum +=weights_length[i].weight * weights_radius[k].weight 
    189                                                 * weights_ratio[l].weight *DiamCyl(dp.length,suf_rad)/2.0; 
    190                                 norm += weights_length[i].weight* weights_radius[k].weight* weights_ratio[l].weight; 
    191                         } 
    192                 } 
    193         } 
    194         if (norm != 0){ 
    195                 //return the averaged value 
    196                 rad_out =  sum/norm;} 
    197         else{ 
    198                 //return normal value 
    199                 //Note: output of "DiamCyl(dp.length,dp.radius)" is DIAMETER. 
    200                 rad_out = DiamCyl(dp.length,suf_rad)/2.0;} 
    201  
    202         return rad_out; 
    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  
    1818 *   sansmodels/src/libigor 
    1919 * 
    20  *      TODO: refactor so that we pull in the old sansmodels.c_extensions 
    2120 *      TODO: add 2d 
    2221 */ 
    2322 
    2423#include <math.h> 
    25 #include "models.hh" 
    2624#include "parameters.hh" 
    2725#include <stdio.h> 
    2826using namespace std; 
     27#include "flexible_cylinder.h" 
    2928 
    3029extern "C" { 
    3130        #include "libCylinder.h" 
    3231        #include "libStructureFactor.h" 
    33         #include "flexible_cylinder.h" 
    3432} 
     33 
     34typedef 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; 
    3543 
    3644FlexibleCylinderModel :: FlexibleCylinderModel() { 
  • sansmodels/src/c_models/fractal.cpp

    r67424cd r82c11d3  
    2121 
    2222#include <math.h> 
    23 #include "models.hh" 
    2423#include "parameters.hh" 
    2524#include <stdio.h> 
    2625using namespace std; 
     26#include "fractal.h" 
    2727 
    2828extern "C" { 
    29         #include "libTwoPhase.h" 
    30         #include "fractal.h" 
     29#include "libTwoPhase.h" 
    3130} 
    3231 
    3332FractalModel :: FractalModel() { 
    34         scale      = Parameter(1.0); 
    35     radius = Parameter(5.0, true); 
    36     radius.set_min(0.0); 
    37     fractal_dim = Parameter(2.0); 
    38     cor_length = Parameter(100.0); 
    39     sldBlock = Parameter(2.0e-6); 
    40     sldSolv= Parameter(6.35e-6); 
    41         background = Parameter(0.0); 
     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); 
    4241} 
    4342 
     
    4948 */ 
    5049double FractalModel :: operator()(double q) { 
    51         double dp[7]; 
     50  double dp[7]; 
    5251 
    53         // Fill parameter array for IGOR library 
    54         // Add the background after averaging 
    55         dp[0] = scale(); 
    56         dp[1] = radius(); 
    57         dp[2] = fractal_dim(); 
    58         dp[3] = cor_length(); 
    59         dp[4] = sldBlock(); 
    60         dp[5] = sldSolv(); 
    61         dp[6] = 0.0; 
     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; 
    6261 
    63         // Get the dispersion points for the radius 
    64         vector<WeightPoint> weights_rad; 
    65         radius.get_weights(weights_rad); 
     62  // Get the dispersion points for the radius 
     63  vector<WeightPoint> weights_rad; 
     64  radius.get_weights(weights_rad); 
    6665 
    67         // Perform the computation, with all weight points 
    68         double sum = 0.0; 
    69         double norm = 0.0; 
    70         double vol = 0.0; 
     66  // Perform the computation, with all weight points 
     67  double sum = 0.0; 
     68  double norm = 0.0; 
     69  double vol = 0.0; 
    7170 
    72         // Loop over radius weight points 
    73         for(size_t i=0; i<weights_rad.size(); i++) { 
    74                 dp[1] = weights_rad[i].value; 
     71  // Loop over radius weight points 
     72  for(size_t i=0; i<weights_rad.size(); i++) { 
     73    dp[1] = weights_rad[i].value; 
    7574 
    76                 //Un-normalize Fractal by volume 
    77                 sum += weights_rad[i].weight 
    78                         * Fractal(dp, fabs(q)) * pow(weights_rad[i].value,3); 
    79                 //Find average volume 
    80                 vol += weights_rad[i].weight 
    81                         * pow(weights_rad[i].value,3); 
     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); 
    8281 
    83                 norm += weights_rad[i].weight; 
    84         } 
     82    norm += weights_rad[i].weight; 
     83  } 
    8584 
    86         if (vol != 0.0 && norm != 0.0) { 
    87                 //Re-normalize by avg volume 
    88                 sum = sum/(vol/norm);} 
    89         return sum/norm + background(); 
     85  if (vol != 0.0 && norm != 0.0) { 
     86    //Re-normalize by avg volume 
     87    sum = sum/(vol/norm);} 
     88  return sum/norm + background(); 
    9089} 
    9190 
     
    9796 */ 
    9897double FractalModel :: operator()(double qx, double qy) { 
    99         double q = sqrt(qx*qx + qy*qy); 
    100         return (*this).operator()(q); 
     98  double q = sqrt(qx*qx + qy*qy); 
     99  return (*this).operator()(q); 
    101100} 
    102101 
     
    109108 */ 
    110109double FractalModel :: evaluate_rphi(double q, double phi) { 
    111         return (*this).operator()(q); 
     110  return (*this).operator()(q); 
    112111} 
    113112 
     
    117116 */ 
    118117double FractalModel :: calculate_ER() { 
    119         //NOT implemented yet!!! 'cause None shape Model 
    120         return 0.0; 
     118  //NOT implemented yet!!! 'cause None shape Model 
     119  return 0.0; 
    121120} 
  • sansmodels/src/c_models/hollowcylinder.cpp

    r67424cd r82c11d3  
    1818 *   sansmodels/src/libigor 
    1919 * 
    20  *      TODO: refactor so that we pull in the old sansmodels.c_extensions 
    2120 */ 
    2221 
    2322#include <math.h> 
    24 #include "models.hh" 
    2523#include "parameters.hh" 
    2624#include <stdio.h> 
    2725using namespace std; 
     26#include "hollow_cylinder.h" 
    2827 
    2928extern "C" { 
    30         #include "libCylinder.h" 
    31         #include "libStructureFactor.h" 
    32         #include "hollow_cylinder.h" 
     29#include "libCylinder.h" 
     30#include "libStructureFactor.h" 
     31} 
     32 
     33typedef 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 */ 
     53static 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 */ 
     114static 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); 
    33118} 
    34119 
    35120HollowCylinderModel :: HollowCylinderModel() { 
    36         scale      = Parameter(1.0); 
    37         core_radius = Parameter(20.0, true); 
    38         core_radius.set_min(0.0); 
    39         radius  = Parameter(30.0, true); 
    40         radius.set_min(0.0); 
    41         length     = Parameter(400.0, true); 
    42         length.set_min(0.0); 
    43         sldCyl  = Parameter(6.3e-6); 
    44         sldSolv  = Parameter(1.0e-6); 
    45         background = Parameter(0.0); 
    46         axis_theta = Parameter(0.0, true); 
    47         axis_phi   = Parameter(0.0, true); 
     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); 
    48133} 
    49134 
     
    55140 */ 
    56141double HollowCylinderModel :: operator()(double q) { 
    57         double dp[7]; 
    58  
    59         dp[0] = scale(); 
    60         dp[1] = core_radius(); 
    61         dp[2] = radius(); 
    62         dp[3] = length(); 
    63         dp[4] = sldCyl(); 
    64         dp[5] = sldSolv(); 
    65         dp[6] = 0.0; 
    66  
    67         // Get the dispersion points for the core radius 
    68         vector<WeightPoint> weights_core_radius; 
    69         core_radius.get_weights(weights_core_radius); 
    70  
    71         // Get the dispersion points for the shell radius 
    72         vector<WeightPoint> weights_radius; 
    73         radius.get_weights(weights_radius); 
    74  
    75         // Get the dispersion points for the length 
    76         vector<WeightPoint> weights_length; 
    77         length.get_weights(weights_length); 
    78  
    79         // Perform the computation, with all weight points 
    80         double sum = 0.0; 
    81         double norm = 0.0; 
    82         double vol = 0.0; 
    83  
    84         // Loop over core radius weight points 
    85         for(int i=0; i< (int)weights_core_radius.size(); i++) { 
    86                 dp[1] = weights_core_radius[i].value; 
    87  
    88                 // Loop over length weight points 
    89                 for(int j=0; j< (int)weights_length.size(); j++) { 
    90                         dp[3] = weights_length[j].value; 
    91  
    92                         // Loop over shell radius weight points 
    93                         for(int k=0; k< (int)weights_radius.size(); k++) { 
    94                                 dp[2] = weights_radius[k].value; 
    95                                 //Un-normalize  by volume 
    96                                 sum += weights_core_radius[i].weight 
    97                                         * weights_length[j].weight 
    98                                         * weights_radius[k].weight 
    99                                         * HollowCylinder(dp, q) 
    100                                         * (pow(weights_radius[k].value,2)-pow(weights_core_radius[i].value,2)) 
    101                                         * weights_length[j].value; 
    102                                 //Find average volume 
    103                                 vol += weights_core_radius[i].weight 
    104                                         * weights_length[j].weight 
    105                                         * weights_radius[k].weight 
    106                                         * (pow(weights_radius[k].value,2)-pow(weights_core_radius[i].value,2)) 
    107                                         * weights_length[j].value; 
    108  
    109                                 norm += weights_core_radius[i].weight 
    110                                         * weights_length[j].weight 
    111                                         * weights_radius[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  
    119         return sum/norm + background(); 
     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(); 
    120205} 
    121206 
     
    127212 */ 
    128213double HollowCylinderModel :: operator()(double qx, double qy) { 
    129         HollowCylinderParameters dp; 
    130         // Fill parameter array 
    131         dp.scale      = scale(); 
    132         dp.core_radius     = core_radius(); 
    133         dp.radius  = radius(); 
    134         dp.length     = length(); 
    135         dp.sldCyl   = sldCyl(); 
    136         dp.sldSolv  = sldSolv(); 
    137         dp.background = 0.0; 
    138         dp.axis_theta = axis_theta(); 
    139         dp.axis_phi   = axis_phi(); 
    140  
    141         // Get the dispersion points for the core radius 
    142         vector<WeightPoint> weights_core_radius; 
    143         core_radius.get_weights(weights_core_radius); 
    144  
    145         // Get the dispersion points for the shell radius 
    146         vector<WeightPoint> weights_radius; 
    147         radius.get_weights(weights_radius); 
    148  
    149         // Get the dispersion points for the length 
    150         vector<WeightPoint> weights_length; 
    151         length.get_weights(weights_length); 
    152  
    153         // Get angular averaging for theta 
    154         vector<WeightPoint> weights_theta; 
    155         axis_theta.get_weights(weights_theta); 
    156  
    157         // Get angular averaging for phi 
    158         vector<WeightPoint> weights_phi; 
    159         axis_phi.get_weights(weights_phi); 
    160  
    161         // Perform the computation, with all weight points 
    162         double sum = 0.0; 
    163         double norm = 0.0; 
    164         double norm_vol = 0.0; 
    165         double vol = 0.0; 
    166         double pi = 4.0*atan(1.0); 
    167         // Loop over core radius weight points 
    168         for(int i=0; i<(int)weights_core_radius.size(); i++) { 
    169                 dp.core_radius = weights_core_radius[i].value; 
    170  
    171  
    172                 // Loop over length weight points 
    173                 for(int j=0; j<(int)weights_length.size(); j++) { 
    174                         dp.length = weights_length[j].value; 
    175  
    176                         // Loop over shell radius weight points 
    177                         for(int m=0; m< (int)weights_radius.size(); m++) { 
    178                                 dp.radius = weights_radius[m].value; 
    179  
    180                         // Average over theta distribution 
    181                         for(int k=0; k< (int)weights_theta.size(); k++) { 
    182                                 dp.axis_theta = weights_theta[k].value; 
    183  
    184                                 // Average over phi distribution 
    185                                 for(int l=0; l< (int)weights_phi.size(); l++) { 
    186                                         dp.axis_phi = weights_phi[l].value; 
    187                                         //Un-normalize by volume 
    188                                         double _ptvalue = weights_core_radius[i].weight 
    189                                                 * weights_length[j].weight 
    190                                                 * weights_radius[m].weight 
    191                                                 * weights_theta[k].weight 
    192                                                 * weights_phi[l].weight 
    193                                                 * hollow_cylinder_analytical_2DXY(&dp, qx, qy) 
    194                                                 / ((pow(weights_radius[m].value,2)-pow(weights_core_radius[i].value,2)) 
    195                                                 * weights_length[j].value); 
    196                                         if (weights_theta.size()>1) { 
    197                                                 _ptvalue *= fabs(sin(weights_theta[k].value * pi/180.0)); 
    198                                         } 
    199                                         sum += _ptvalue; 
    200                                         //Find average volume 
    201                                         vol += weights_core_radius[i].weight 
    202                                                 * weights_length[j].weight 
    203                                                 * weights_radius[m].weight 
    204                                                 * (pow(weights_radius[m].value,2)-pow(weights_core_radius[i].value,2)) 
    205                                                 * weights_length[j].value; 
    206                                         //Find norm for volume 
    207                                         norm_vol += weights_core_radius[i].weight 
    208                                                 * weights_length[j].weight 
    209                                                 * weights_radius[m].weight; 
    210  
    211                                         norm += weights_core_radius[i].weight 
    212                                                 * weights_length[j].weight 
    213                                                 * weights_radius[m].weight 
    214                                                 * weights_theta[k].weight 
    215                                                 * weights_phi[l].weight; 
    216  
    217                                 } 
    218                         } 
    219                         } 
    220                 } 
    221         } 
    222         // Averaging in theta needs an extra normalization 
    223         // factor to account for the sin(theta) term in the 
    224         // integration (see documentation). 
    225         if (weights_theta.size()>1) norm = norm/asin(1.0); 
    226         if (vol != 0.0 || norm_vol != 0.0) { 
    227                 //Re-normalize by avg volume 
    228                 sum = sum*(vol/norm_vol);} 
    229         return sum/norm + background(); 
     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(); 
    230315} 
    231316 
     
    238323 */ 
    239324double HollowCylinderModel :: evaluate_rphi(double q, double phi) { 
    240         double qx = q*cos(phi); 
    241         double qy = q*sin(phi); 
    242         return (*this).operator()(qx, qy); 
     325  double qx = q*cos(phi); 
     326  double qy = q*sin(phi); 
     327  return (*this).operator()(qx, qy); 
    243328} 
    244329/** 
     
    247332 */ 
    248333double HollowCylinderModel :: calculate_ER() { 
    249         HollowCylinderParameters dp; 
    250  
    251         dp.radius  = radius(); 
    252         dp.length     = length(); 
    253  
    254         double rad_out = 0.0; 
    255  
    256         // Perform the computation, with all weight points 
    257         double sum = 0.0; 
    258         double norm = 0.0; 
    259  
    260         // Get the dispersion points for the major shell 
    261         vector<WeightPoint> weights_length; 
    262         length.get_weights(weights_length); 
    263  
    264         // Get the dispersion points for the minor shell 
    265         vector<WeightPoint> weights_radius ; 
    266         radius.get_weights(weights_radius); 
    267  
    268         // Loop over major shell weight points 
    269         for(int i=0; i< (int)weights_length.size(); i++) { 
    270                 dp.length = weights_length[i].value; 
    271                 for(int k=0; k< (int)weights_radius.size(); k++) { 
    272                         dp.radius = weights_radius[k].value; 
    273                         //Note: output of "DiamCyl(dp.length,dp.radius)" is DIAMETER. 
    274                         sum +=weights_length[i].weight 
    275                                 * weights_radius[k].weight*DiamCyl(dp.length,dp.radius)/2.0; 
    276                         norm += weights_length[i].weight* weights_radius[k].weight; 
    277                 } 
    278         } 
    279         if (norm != 0){ 
    280                 //return the averaged value 
    281                 rad_out =  sum/norm;} 
    282         else{ 
    283                 //return normal value 
    284                 //Note: output of "DiamCyl(dp.length,dp.radius)" is DIAMETER. 
    285                 rad_out = DiamCyl(dp.length,dp.radius)/2.0;} 
    286  
    287         return rad_out; 
    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  
    1818 *   sansmodels/src/libigor 
    1919 * 
    20  *      TODO: refactor so that we pull in the old sansmodels.c_extensions 
    2120 */ 
    2221 
    2322#include <math.h> 
    24 #include "models.hh" 
    2523#include "parameters.hh" 
    2624#include <stdio.h> 
    2725using namespace std; 
     26#include "lamellar.h" 
    2827 
    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*/ 
     31static 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); 
    3255} 
    3356 
     
    3962        sld_sol    = Parameter(6.3e-6); 
    4063        background = Parameter(0.0); 
    41  
    4264} 
    4365 
  • sansmodels/src/c_models/lamellarFF_HG.cpp

    r67424cd r82c11d3  
    1818 *   sansmodels/src/libigor 
    1919 * 
    20  *      TODO: refactor so that we pull in the old sansmodels.c_extensions 
    2120 */ 
    2221 
    2322#include <math.h> 
    24 #include "models.hh" 
    2523#include "parameters.hh" 
    2624#include <stdio.h> 
    2725using namespace std; 
     26#include "lamellarFF_HG.h" 
    2827 
    2928extern "C" { 
    30         #include "libCylinder.h" 
    31         #include "lamellarFF_HG.h" 
     29#include "libCylinder.h" 
    3230} 
    3331 
    3432LamellarFFHGModel :: LamellarFFHGModel() { 
    35         scale      = Parameter(1.0); 
    36         t_length     = Parameter(15.0, true); 
    37         t_length.set_min(0.0); 
    38         h_thickness    = Parameter(10.0, true); 
    39         h_thickness.set_min(0.0); 
    40         sld_tail   = Parameter(4e-7); 
    41         sld_head  = Parameter(3e-6); 
    42         sld_solvent    = Parameter(6e-6); 
    43         background = Parameter(0.0); 
     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); 
    4442 
    4543} 
     
    5250 */ 
    5351double LamellarFFHGModel :: operator()(double q) { 
    54         double dp[7]; 
     52  double dp[7]; 
    5553 
    56         // Fill parameter array for IGOR library 
    57         // Add the background after averaging 
    58         dp[0] = scale(); 
    59         dp[1] = t_length(); 
    60         dp[2] = h_thickness(); 
    61         dp[3] = sld_tail(); 
    62         dp[4] = sld_head(); 
    63         dp[5] = sld_solvent(); 
    64         dp[6] = 0.0; 
     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; 
    6563 
    66         // Get the dispersion points for the tail length 
    67         vector<WeightPoint> weights_t_length; 
    68         t_length.get_weights(weights_t_length); 
     64  // Get the dispersion points for the tail length 
     65  vector<WeightPoint> weights_t_length; 
     66  t_length.get_weights(weights_t_length); 
    6967 
    70         // Get the dispersion points for the head thickness 
    71         vector<WeightPoint> weights_h_thickness; 
    72         h_thickness.get_weights(weights_h_thickness); 
     68  // Get the dispersion points for the head thickness 
     69  vector<WeightPoint> weights_h_thickness; 
     70  h_thickness.get_weights(weights_h_thickness); 
    7371 
    74         // Perform the computation, with all weight points 
    75         double sum = 0.0; 
    76         double norm = 0.0; 
     72  // Perform the computation, with all weight points 
     73  double sum = 0.0; 
     74  double norm = 0.0; 
    7775 
    78         // Loop over semi axis A weight points 
    79         for(int i=0; i< (int)weights_t_length.size(); i++) { 
    80                 dp[1] = weights_t_length[i].value; 
     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; 
    8179 
    82                 for (int j=0; j< (int)weights_h_thickness.size(); j++){ 
    83                         dp[2] = weights_h_thickness[j].value; 
     80    for (int j=0; j< (int)weights_h_thickness.size(); j++){ 
     81      dp[2] = weights_h_thickness[j].value; 
    8482 
    85                         sum += weights_t_length[i].weight* weights_h_thickness[j].weight*LamellarFF_HG(dp, q); 
    86                         norm += weights_t_length[i].weight* weights_h_thickness[j].weight; 
    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    } 
    8886 
    89         } 
    90         return sum/norm + background(); 
     87  } 
     88  return sum/norm + background(); 
    9189} 
    9290 
     
    9997 
    10098double LamellarFFHGModel :: operator()(double qx, double qy) { 
    101         double q = sqrt(qx*qx + qy*qy); 
    102         return (*this).operator()(q); 
     99  double q = sqrt(qx*qx + qy*qy); 
     100  return (*this).operator()(q); 
    103101} 
    104102 
     
    111109 */ 
    112110double LamellarFFHGModel :: evaluate_rphi(double q, double phi) { 
    113         return (*this).operator()(q); 
     111  return (*this).operator()(q); 
    114112} 
    115113/** 
     
    118116 */ 
    119117double LamellarFFHGModel :: calculate_ER() { 
    120 //NOT implemented yet!!! 
    121         return 0.0; 
     118  //NOT implemented yet!!! 
     119  return 0.0; 
    122120} 
  • sansmodels/src/c_models/lamellarPC.cpp

    r67424cd r82c11d3  
    2020 
    2121#include <math.h> 
    22 #include "models.hh" 
    2322#include "parameters.hh" 
    2423#include <stdio.h> 
    2524using namespace std; 
     25#include "lamellarPC.h" 
    2626 
    2727extern "C" { 
    28         #include "libCylinder.h" 
    29         #include "lamellarPC.h" 
     28#include "libCylinder.h" 
    3029} 
    3130 
    3231LamellarPCrystalModel :: LamellarPCrystalModel() { 
    33         scale      = Parameter(1.0); 
    34         thickness     = Parameter(33.0, true); 
    35         thickness.set_min(0.0); 
    36         Nlayers    = Parameter(20.0, true); 
    37         Nlayers.set_min(0.0); 
    38         spacing   = Parameter(250); 
    39         pd_spacing   = Parameter(0.0); 
    40         sld_layer  = Parameter(1.0e-6); 
    41         sld_solvent    = Parameter(6.34e-6); 
    42         background = Parameter(0.0); 
     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); 
    4342 
    4443} 
     
    5150 */ 
    5251double LamellarPCrystalModel :: operator()(double q) { 
    53         double dp[8]; 
     52  double dp[8]; 
    5453 
    55         // Fill parameter array for IGOR library 
    56         // Add the background after averaging 
    57         dp[0] = scale(); 
    58         dp[1] = thickness(); 
    59         dp[2] = Nlayers(); 
    60         dp[3] = spacing(); 
    61         dp[4] = pd_spacing(); 
    62         dp[5] = sld_layer(); 
    63         dp[6] = sld_solvent(); 
    64         dp[7] = 0.0; // Do not apply background here. 
     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. 
    6564 
    66         // Get the dispersion points for the head thickness 
    67         vector<WeightPoint> weights_thickness; 
    68         thickness.get_weights(weights_thickness); 
     65  // Get the dispersion points for the head thickness 
     66  vector<WeightPoint> weights_thickness; 
     67  thickness.get_weights(weights_thickness); 
    6968 
    70         // Let's provide from the func which is more accurate especially for small q region. 
    71         // Get the dispersion points for the tail length 
    72         //vector<WeightPoint> weights_spacing; 
    73         //spacing.get_weights(weights_spacing); 
     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); 
    7473 
    75         // Perform the computation, with all weight points 
    76         double sum = 0.0; 
    77         double norm = 0.0; 
     74  // Perform the computation, with all weight points 
     75  double sum = 0.0; 
     76  double norm = 0.0; 
    7877 
    79         // Loop over thickness and spacing weight points 
    80         for(int i=0; i< (int)weights_thickness.size(); i++) { 
    81                 dp[1] = weights_thickness[i].value; 
    82                 //for (int j=0; j< (int)weights_spacing.size(); j++){ 
    83                         //dp[3] = weights_spacing[j].value; 
    84                         sum += weights_thickness[i].weight*Lamellar_ParaCrystal(dp, q); 
    85                         norm += weights_thickness[i].weight; 
    86                 //} 
    87         } 
    88         //apply norm and background 
    89         return sum/norm + background(); 
     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(); 
    9089} 
    9190 
     
    9897 
    9998double LamellarPCrystalModel :: operator()(double qx, double qy) { 
    100         double q = sqrt(qx*qx + qy*qy); 
    101         return (*this).operator()(q); 
     99  double q = sqrt(qx*qx + qy*qy); 
     100  return (*this).operator()(q); 
    102101} 
    103102 
     
    110109 */ 
    111110double LamellarPCrystalModel :: evaluate_rphi(double q, double phi) { 
    112         return (*this).operator()(q); 
     111  return (*this).operator()(q); 
    113112} 
    114113/** 
     
    117116 */ 
    118117double LamellarPCrystalModel :: calculate_ER() { 
    119 //NOT implemented yet!!! 
    120         return 0.0; 
     118  //NOT implemented yet!!! 
     119  return 0.0; 
    121120} 
  • sansmodels/src/c_models/lamellarPS.cpp

    r67424cd r82c11d3  
    2323 
    2424#include <math.h> 
    25 #include "models.hh" 
    2625#include "parameters.hh" 
    2726#include <stdio.h> 
     27#include <stdlib.h> 
    2828using namespace std; 
     29#include "lamellarPS.h" 
    2930 
    3031extern "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 */ 
     41static 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); 
    3396} 
    3497 
    3598LamellarPSModel :: LamellarPSModel() { 
    36         scale      = Parameter(1.0); 
    37         spacing    = Parameter(400.0, true); 
    38         spacing.set_min(0.0); 
    39         delta     = Parameter(30.0); 
    40         delta.set_min(0.0); 
    41         sld_bi   = Parameter(6.3e-6); 
    42         sld_sol   = Parameter(1.0e-6); 
    43         n_plates     = Parameter(20.0); 
    44         caille = Parameter(0.1); 
    45         background = Parameter(0.0); 
     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); 
    46109 
    47110} 
     
    54117 */ 
    55118double LamellarPSModel :: operator()(double q) { 
    56         double dp[8]; 
     119  double dp[8]; 
    57120 
    58         // Fill parameter array for IGOR library 
    59         // Add the background after averaging 
    60         dp[0] = scale(); 
    61         dp[1] = spacing(); 
    62         dp[2] = delta(); 
    63         dp[3] = sld_bi(); 
    64         dp[4] = sld_sol(); 
    65         dp[5] = n_plates(); 
    66         dp[6] = caille(); 
    67         dp[7] = 0.0; 
     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; 
    68131 
    69132 
    70         // Get the dispersion points for spacing and delta (thickness) 
    71         vector<WeightPoint> weights_spacing; 
    72         spacing.get_weights(weights_spacing); 
    73         vector<WeightPoint> weights_delta; 
    74         delta.get_weights(weights_delta); 
     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); 
    75138 
    76         // Perform the computation, with all weight points 
    77         double sum = 0.0; 
    78         double norm = 0.0; 
     139  // Perform the computation, with all weight points 
     140  double sum = 0.0; 
     141  double norm = 0.0; 
    79142 
    80         // Loop over short_edgeA weight points 
    81         for(int i=0; i< (int)weights_spacing.size(); i++) { 
    82                 dp[1] = weights_spacing[i].value; 
    83                 for(int j=0; j< (int)weights_spacing.size(); j++) { 
    84                         dp[2] = weights_delta[i].value; 
     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; 
    85148 
    86                         sum += weights_spacing[i].weight * weights_delta[j].weight * LamellarPS_kernel(dp, q); 
    87                         norm += weights_spacing[i].weight * weights_delta[j].weight; 
    88                 } 
    89         } 
    90         return sum/norm + background(); 
     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(); 
    91154} 
    92155/** 
     
    97160 */ 
    98161double LamellarPSModel :: operator()(double qx, double qy) { 
    99         double q = sqrt(qx*qx + qy*qy); 
    100         return (*this).operator()(q); 
     162  double q = sqrt(qx*qx + qy*qy); 
     163  return (*this).operator()(q); 
    101164} 
    102165 
     
    109172 */ 
    110173double LamellarPSModel :: evaluate_rphi(double q, double phi) { 
    111         return (*this).operator()(q); 
     174  return (*this).operator()(q); 
    112175} 
    113176/** 
     
    116179 */ 
    117180double LamellarPSModel :: calculate_ER() { 
    118 //NOT implemented yet!!! 
    119         return 0.0; 
     181  //NOT implemented yet!!! 
     182  return 0.0; 
    120183} 
    121184 
  • sansmodels/src/c_models/lamellarPS_HG.cpp

    r67424cd r82c11d3  
    1818 *   sansmodels/src/libigor 
    1919 * 
    20  *      TODO: refactor so that we pull in the old sansmodels.c_extensions 
    2120 *      TODO: add 2D function 
    2221 */ 
    2322 
    2423#include <math.h> 
    25 #include "models.hh" 
    2624#include "parameters.hh" 
    2725#include <stdio.h> 
    2826using namespace std; 
     27#include "lamellarPS_HG.h" 
    2928 
    3029extern "C" { 
    3130        #include "libCylinder.h" 
    32         #include "lamellarPS_HG.h" 
    3331} 
    3432 
     
    137135        return 0.0; 
    138136} 
    139  
    140 /* 
    141 double LamellarPSHGModel :: operator()(double qx, double qy) { 
    142         LamellarPSHGParameters dp; 
    143         // Fill parameter array 
    144         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 deltaT 
    156         vector<WeightPoint> weights_deltaT; 
    157         deltaT.get_weights(weights_deltaT); 
    158  
    159         // Get the dispersion points for the deltaH 
    160         vector<WeightPoint> weights_deltaH; 
    161         deltaH.get_weights(weights_deltaH); 
    162  
    163         // Perform the computation, with all weight points 
    164         double sum = 0.0; 
    165         double norm = 0.0; 
    166  
    167         // Loop over deltaT weight points 
    168         for(int i=0; i< (int)weights_deltaT.size(); i++) { 
    169                 dp.deltaT = weights_deltaT[i].value; 
    170  
    171                 // Loop over deltaH weight points 
    172                 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  
    2121 
    2222#include <math.h> 
    23 #include "models.hh" 
    2423#include "parameters.hh" 
    2524#include <stdio.h> 
    2625using namespace std; 
     26#include "multishell.h" 
    2727 
    2828extern "C" { 
    29         #include "libSphere.h" 
    30         #include "multishell.h" 
     29#include "libSphere.h" 
    3130} 
    3231 
     32typedef 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 
    3344MultiShellModel :: MultiShellModel() { 
    34         scale      = Parameter(1.0); 
    35         core_radius     = Parameter(60.0, true); 
    36         core_radius.set_min(0.0); 
    37         s_thickness  = Parameter(10.0, true); 
    38         s_thickness.set_min(0.0); 
    39         w_thickness   = Parameter(10.0, true); 
    40         w_thickness.set_min(0.0); 
    41         core_sld   = Parameter(6.4e-6); 
    42         shell_sld   = Parameter(4.0e-7); 
    43         n_pairs   = Parameter(2); 
    44         background = Parameter(0.0); 
     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); 
    4556} 
    4657 
     
    5263 */ 
    5364double MultiShellModel :: operator()(double q) { 
    54         double dp[8]; 
     65  double dp[8]; 
    5566 
    56         // Fill parameter array for IGOR library 
    57         // Add the background after averaging 
    58         dp[0] = scale(); 
    59         dp[1] = core_radius(); 
    60         dp[2] = s_thickness(); 
    61         dp[3] = w_thickness(); 
    62         dp[4] = core_sld(); 
    63         dp[5] = shell_sld(); 
    64         dp[6] = n_pairs(); 
    65         dp[7] = 0.0; 
     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; 
    6677 
    67         // Get the dispersion points for the core radius 
    68         vector<WeightPoint> weights_core_radius; 
    69         core_radius.get_weights(weights_core_radius); 
     78  // Get the dispersion points for the core radius 
     79  vector<WeightPoint> weights_core_radius; 
     80  core_radius.get_weights(weights_core_radius); 
    7081 
    71         // Get the dispersion points for the s_thickness 
    72         vector<WeightPoint> weights_s_thickness; 
    73         s_thickness.get_weights(weights_s_thickness); 
     82  // Get the dispersion points for the s_thickness 
     83  vector<WeightPoint> weights_s_thickness; 
     84  s_thickness.get_weights(weights_s_thickness); 
    7485 
    75         // Get the dispersion points for the w_thickness 
    76         vector<WeightPoint> weights_w_thickness; 
    77         w_thickness.get_weights(weights_w_thickness); 
     86  // Get the dispersion points for the w_thickness 
     87  vector<WeightPoint> weights_w_thickness; 
     88  w_thickness.get_weights(weights_w_thickness); 
    7889 
    79         // Perform the computation, with all weight points 
    80         double sum = 0.0; 
    81         double norm = 0.0; 
    82         double vol = 0.0; 
     90  // Perform the computation, with all weight points 
     91  double sum = 0.0; 
     92  double norm = 0.0; 
     93  double vol = 0.0; 
    8394 
    84         // Loop over radius weight points 
    85         for(int i=0; i< (int)weights_core_radius.size(); i++) { 
    86                 dp[1] = weights_core_radius[i].value; 
    87                 for(int j=0; j< (int)weights_s_thickness.size(); j++){ 
    88                         dp[2] = weights_s_thickness[j].value; 
    89                         for(int k=0; k< (int)weights_w_thickness.size(); k++){ 
    90                                 dp[3] = weights_w_thickness[k].value; 
    91                                 //Un-normalize SphereForm by volume 
    92                                 sum += weights_core_radius[i].weight*weights_s_thickness[j].weight 
    93                                         *weights_w_thickness[k].weight* MultiShell(dp, q) 
    94                                         *pow(weights_core_radius[i].value+dp[6]*weights_s_thickness[j].value+(dp[6]-1)*weights_w_thickness[k].value,3); 
    95                                 //Find average volume 
    96                                 vol += weights_core_radius[i].weight*weights_s_thickness[j].weight 
    97                                         *weights_w_thickness[k].weight 
    98                                         *pow(weights_core_radius[i].value+dp[6]*weights_s_thickness[j].value+(dp[6]-1)*weights_w_thickness[k].value,3); 
    99                                 norm += weights_core_radius[i].weight*weights_s_thickness[j].weight 
    100                                         *weights_w_thickness[k].weight; 
    101                         } 
    102                 } 
    103         } 
    104         if (vol != 0.0 && norm != 0.0) { 
    105                 //Re-normalize by avg volume 
    106                 sum = sum/(vol/norm);} 
    107         return sum/norm + background(); 
     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(); 
    108119} 
    109120 
     
    115126 */ 
    116127double MultiShellModel :: operator()(double qx, double qy) { 
    117         double q = sqrt(qx*qx + qy*qy); 
    118         return (*this).operator()(q); 
     128  double q = sqrt(qx*qx + qy*qy); 
     129  return (*this).operator()(q); 
    119130} 
    120131 
     
    127138 */ 
    128139double MultiShellModel :: evaluate_rphi(double q, double phi) { 
    129         return (*this).operator()(q); 
     140  return (*this).operator()(q); 
    130141} 
    131142/** 
     
    134145 */ 
    135146double MultiShellModel :: calculate_ER() { 
    136         MultiShellParameters dp; 
     147  MultiShellParameters dp; 
    137148 
    138         dp.core_radius     = core_radius(); 
    139         dp.s_thickness  = s_thickness(); 
    140         dp.w_thickness  = w_thickness(); 
    141         dp.n_pairs = n_pairs(); 
     149  dp.core_radius     = core_radius(); 
     150  dp.s_thickness  = s_thickness(); 
     151  dp.w_thickness  = w_thickness(); 
     152  dp.n_pairs = n_pairs(); 
    142153 
    143         double rad_out = 0.0; 
     154  double rad_out = 0.0; 
    144155 
    145         // Perform the computation, with all weight points 
    146         double sum = 0.0; 
    147         double norm = 0.0; 
    148         if (dp.n_pairs <= 0.0 ){ 
    149                 dp.n_pairs = 0.0; 
    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  } 
    151162 
    152         // Get the dispersion points for the core radius 
    153         vector<WeightPoint> weights_core_radius; 
    154         core_radius.get_weights(weights_core_radius); 
     163  // Get the dispersion points for the core radius 
     164  vector<WeightPoint> weights_core_radius; 
     165  core_radius.get_weights(weights_core_radius); 
    155166 
    156         // Get the dispersion points for the s_thickness 
    157         vector<WeightPoint> weights_s_thickness; 
    158         s_thickness.get_weights(weights_s_thickness); 
     167  // Get the dispersion points for the s_thickness 
     168  vector<WeightPoint> weights_s_thickness; 
     169  s_thickness.get_weights(weights_s_thickness); 
    159170 
    160         // Get the dispersion points for the w_thickness 
    161         vector<WeightPoint> weights_w_thickness; 
    162         w_thickness.get_weights(weights_w_thickness); 
     171  // Get the dispersion points for the w_thickness 
     172  vector<WeightPoint> weights_w_thickness; 
     173  w_thickness.get_weights(weights_w_thickness); 
    163174 
    164         // Loop over major shell weight points 
    165         for(int i=0; i< (int)weights_s_thickness.size(); i++) { 
    166                 dp.s_thickness = weights_s_thickness[i].value; 
    167                 for(int j=0; j< (int)weights_w_thickness.size(); j++) { 
    168                         dp.w_thickness = weights_w_thickness[j].value; 
    169                         for(int k=0; k< (int)weights_core_radius.size(); k++) { 
    170                                 dp.core_radius = weights_core_radius[k].value; 
    171                                 sum += weights_s_thickness[i].weight*weights_w_thickness[j].weight 
    172                                         * weights_core_radius[k].weight*(dp.core_radius+dp.n_pairs*dp.s_thickness+(dp.n_pairs-1.0)*dp.w_thickness); 
    173                                 norm += weights_s_thickness[i].weight*weights_w_thickness[j].weight* weights_core_radius[k].weight; 
    174                         } 
    175                 } 
    176         } 
    177         if (norm != 0){ 
    178                 //return the averaged value 
    179                 rad_out =  sum/norm;} 
    180         else{ 
    181                 //return normal value 
    182                 rad_out = (dp.core_radius+dp.n_pairs*dp.s_thickness+(dp.n_pairs-1.0)*dp.w_thickness);} 
     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);} 
    183194 
    184         return rad_out; 
     195  return rad_out; 
    185196} 
  • sansmodels/src/c_models/parallelepiped.cpp

    r8343e18 r82c11d3  
    2222 
    2323#include <math.h> 
    24 #include "models.hh" 
    2524#include "parameters.hh" 
    2625#include <stdio.h> 
  • sansmodels/src/c_models/polygausscoil.cpp

    r67424cd r82c11d3  
    2121 
    2222#include <math.h> 
    23 #include "models.hh" 
    2423#include "parameters.hh" 
    2524#include <stdio.h> 
    2625using namespace std; 
     26#include "polygausscoil.h" 
    2727 
    2828extern "C" { 
    2929        #include "libTwoPhase.h" 
    30         #include "polygausscoil.h" 
    3130} 
    3231 
  • sansmodels/src/c_models/sc.cpp

    r6e10cff r82c11d3  
    2121 
    2222#include <math.h> 
    23 #include "models.hh" 
    2423#include "parameters.hh" 
    2524#include <stdio.h> 
  • sansmodels/src/c_models/sphere.cpp

    ra8eab1c r82c11d3  
    2121 
    2222#include <math.h> 
    23 #include "models.hh" 
    2423#include "parameters.hh" 
    2524#include <stdio.h> 
  • sansmodels/src/c_models/spheroid.cpp

    r67424cd r82c11d3  
    1818 *   sansmodels/src/libigor 
    1919 * 
    20  *      TODO: refactor so that we pull in the old sansmodels.c_extensions 
    2120 */ 
    2221 
    2322#include <math.h> 
    24 #include "models.hh" 
    2523#include "parameters.hh" 
    2624#include <stdio.h> 
     25#include <stdlib.h> 
    2726using namespace std; 
     27#include "spheroid.h" 
    2828 
    2929extern "C" { 
    30         #include "libCylinder.h" 
    31         #include "libStructureFactor.h" 
    32         #include "spheroid.h" 
     30#include "libCylinder.h" 
     31#include "libStructureFactor.h" 
     32} 
     33 
     34typedef 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 */ 
     57static 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; 
    33115} 
    34116 
    35117CoreShellEllipsoidModel :: 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 */ 
     143static 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); 
    52147} 
    53148 
     
    59154 */ 
    60155double CoreShellEllipsoidModel :: operator()(double q) { 
    61         double dp[9]; 
    62  
    63         // Fill parameter array for IGOR library 
    64         // Add the background after averaging 
    65         dp[0] = scale(); 
    66         dp[1] = equat_core(); 
    67         dp[2] = polar_core(); 
    68         dp[3] = equat_shell(); 
    69         dp[4] = polar_shell(); 
    70         dp[5] = sld_core(); 
    71         dp[6] = sld_shell(); 
    72         dp[7] = sld_solvent(); 
    73         dp[8] = 0.0; 
    74  
    75         // Get the dispersion points for the major core 
    76         vector<WeightPoint> weights_equat_core; 
    77         equat_core.get_weights(weights_equat_core); 
    78  
    79         // Get the dispersion points for the minor core 
    80         vector<WeightPoint> weights_polar_core; 
    81         polar_core.get_weights(weights_polar_core); 
    82  
    83         // Get the dispersion points for the major shell 
    84         vector<WeightPoint> weights_equat_shell; 
    85         equat_shell.get_weights(weights_equat_shell); 
    86  
    87         // Get the dispersion points for the minor_shell 
    88         vector<WeightPoint> weights_polar_shell; 
    89         polar_shell.get_weights(weights_polar_shell); 
    90  
    91  
    92         // Perform the computation, with all weight points 
    93         double sum = 0.0; 
    94         double norm = 0.0; 
    95         double vol = 0.0; 
    96  
    97         // Loop over major core weight points 
    98         for(int i=0; i<(int)weights_equat_core.size(); i++) { 
    99                 dp[1] = weights_equat_core[i].value; 
    100  
    101                 // Loop over minor core weight points 
    102                 for(int j=0; j<(int)weights_polar_core.size(); j++) { 
    103                         dp[2] = weights_polar_core[j].value; 
    104  
    105                         // Loop over major shell weight points 
    106                         for(int k=0; k<(int)weights_equat_shell.size(); k++) { 
    107                                 dp[3] = weights_equat_shell[k].value; 
    108  
    109                                 // Loop over minor shell weight points 
    110                                 for(int l=0; l<(int)weights_polar_shell.size(); l++) { 
    111                                         dp[4] = weights_polar_shell[l].value; 
    112                                         //Un-normalize  by volume 
    113                                         sum += weights_equat_core[i].weight* weights_polar_core[j].weight * weights_equat_shell[k].weight 
    114                                                 * weights_polar_shell[l].weight * OblateForm(dp, q) 
    115                                                 * pow(weights_equat_shell[k].value,2)*weights_polar_shell[l].value; 
    116                                         //Find average volume 
    117                                         vol += weights_equat_core[i].weight* weights_polar_core[j].weight 
    118                                                 * weights_equat_shell[k].weight 
    119                                                 * weights_polar_shell[l].weight 
    120                                                 * pow(weights_equat_shell[k].value,2)*weights_polar_shell[l].value; 
    121                                         norm += weights_equat_core[i].weight* weights_polar_core[j].weight * weights_equat_shell[k].weight 
    122                                                         * weights_polar_shell[l].weight; 
    123                                 } 
    124                         } 
    125                 } 
    126         } 
    127         if (vol != 0.0 && norm != 0.0) { 
    128                 //Re-normalize by avg volume 
    129                 sum = sum/(vol/norm);} 
    130         return sum/norm + background(); 
     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(); 
    131226} 
    132227 
     
    143238        return (*this).operator()(q); 
    144239} 
    145 */ 
     240 */ 
    146241 
    147242/** 
     
    153248 */ 
    154249double CoreShellEllipsoidModel :: evaluate_rphi(double q, double phi) { 
    155         double qx = q*cos(phi); 
    156         double qy = q*sin(phi); 
    157         return (*this).operator()(qx, qy); 
     250  double qx = q*cos(phi); 
     251  double qy = q*sin(phi); 
     252  return (*this).operator()(qx, qy); 
    158253} 
    159254 
     
    165260 */ 
    166261double CoreShellEllipsoidModel :: operator()(double qx, double qy) { 
    167         SpheroidParameters dp; 
    168         // Fill parameter array 
    169         dp.scale      = scale(); 
    170         dp.equat_core = equat_core(); 
    171         dp.polar_core = polar_core(); 
    172         dp.equat_shell = equat_shell(); 
    173         dp.polar_shell = polar_shell(); 
    174         dp.sld_core = sld_core(); 
    175         dp.sld_shell = sld_shell(); 
    176         dp.sld_solvent = sld_solvent(); 
    177         dp.background = 0.0; 
    178         dp.axis_theta = axis_theta(); 
    179         dp.axis_phi = axis_phi(); 
    180  
    181         // Get the dispersion points for the major core 
    182         vector<WeightPoint> weights_equat_core; 
    183         equat_core.get_weights(weights_equat_core); 
    184  
    185         // Get the dispersion points for the minor core 
    186         vector<WeightPoint> weights_polar_core; 
    187         polar_core.get_weights(weights_polar_core); 
    188  
    189         // Get the dispersion points for the major shell 
    190         vector<WeightPoint> weights_equat_shell; 
    191         equat_shell.get_weights(weights_equat_shell); 
    192  
    193         // Get the dispersion points for the minor shell 
    194         vector<WeightPoint> weights_polar_shell; 
    195         polar_shell.get_weights(weights_polar_shell); 
    196  
    197  
    198         // Get angular averaging for theta 
    199         vector<WeightPoint> weights_theta; 
    200         axis_theta.get_weights(weights_theta); 
    201  
    202         // Get angular averaging for phi 
    203         vector<WeightPoint> weights_phi; 
    204         axis_phi.get_weights(weights_phi); 
    205  
    206         // Perform the computation, with all weight points 
    207         double sum = 0.0; 
    208         double norm = 0.0; 
    209         double norm_vol = 0.0; 
    210         double vol = 0.0; 
    211         double pi = 4.0*atan(1.0); 
    212         // Loop over major core weight points 
    213         for(int i=0; i< (int)weights_equat_core.size(); i++) { 
    214                 dp.equat_core = weights_equat_core[i].value; 
    215  
    216                 // Loop over minor core weight points 
    217                 for(int j=0; j< (int)weights_polar_core.size(); j++) { 
    218                         dp.polar_core = weights_polar_core[j].value; 
    219  
    220                         // Loop over major shell weight points 
    221                         for(int k=0; k< (int)weights_equat_shell.size(); k++) { 
    222                                 dp.equat_shell = weights_equat_shell[i].value; 
    223  
    224                                 // Loop over minor shell weight points 
    225                                 for(int l=0; l< (int)weights_polar_shell.size(); l++) { 
    226                                         dp.polar_shell = weights_polar_shell[l].value; 
    227  
    228                                         // Average over theta distribution 
    229                                         for(int m=0; m< (int)weights_theta.size(); m++) { 
    230                                                 dp.axis_theta = weights_theta[m].value; 
    231  
    232                                                 // Average over phi distribution 
    233                                                 for(int n=0; n< (int)weights_phi.size(); n++) { 
    234                                                         dp.axis_phi = weights_phi[n].value; 
    235                                                         //Un-normalize by volume 
    236                                                         double _ptvalue = weights_equat_core[i].weight *weights_polar_core[j].weight 
    237                                                                 * weights_equat_shell[k].weight * weights_polar_shell[l].weight 
    238                                                                 * weights_theta[m].weight 
    239                                                                 * weights_phi[n].weight 
    240                                                                 * spheroid_analytical_2DXY(&dp, qx, qy) 
    241                                                                 * pow(weights_equat_shell[k].value,2)*weights_polar_shell[l].value; 
    242                                                         if (weights_theta.size()>1) { 
    243                                                                 _ptvalue *= fabs(sin(weights_theta[m].value*pi/180.0)); 
    244                                                         } 
    245                                                         sum += _ptvalue; 
    246                                                         //Find average volume 
    247                                                         vol += weights_equat_shell[k].weight 
    248                                                                 * weights_polar_shell[l].weight 
    249                                                                 * pow(weights_equat_shell[k].value,2)*weights_polar_shell[l].value; 
    250                                                         //Find norm for volume 
    251                                                         norm_vol += weights_equat_shell[k].weight 
    252                                                                 * weights_polar_shell[l].weight; 
    253  
    254                                                         norm += weights_equat_core[i].weight *weights_polar_core[j].weight 
    255                                                                 * weights_equat_shell[k].weight * weights_polar_shell[l].weight 
    256                                                                 * weights_theta[m].weight * weights_phi[n].weight; 
    257                                                 } 
    258                                         } 
    259                                 } 
    260                         } 
    261                 } 
    262         } 
    263         // Averaging in theta needs an extra normalization 
    264         // factor to account for the sin(theta) term in the 
    265         // integration (see documentation). 
    266         if (weights_theta.size()>1) norm = norm / asin(1.0); 
    267  
    268         if (vol != 0.0 && norm_vol != 0.0) { 
    269                 //Re-normalize by avg volume 
    270                 sum = sum/(vol/norm_vol);} 
    271  
    272         return sum/norm + background(); 
     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(); 
    273368} 
    274369 
     
    278373 */ 
    279374double CoreShellEllipsoidModel :: calculate_ER() { 
    280         SpheroidParameters dp; 
    281  
    282         dp.equat_shell = equat_shell(); 
    283         dp.polar_shell = polar_shell(); 
    284  
    285         double rad_out = 0.0; 
    286  
    287         // Perform the computation, with all weight points 
    288         double sum = 0.0; 
    289         double norm = 0.0; 
    290  
    291         // Get the dispersion points for the major shell 
    292         vector<WeightPoint> weights_equat_shell; 
    293         equat_shell.get_weights(weights_equat_shell); 
    294  
    295         // Get the dispersion points for the minor shell 
    296         vector<WeightPoint> weights_polar_shell; 
    297         polar_shell.get_weights(weights_polar_shell); 
    298  
    299         // Loop over major shell weight points 
    300         for(int i=0; i< (int)weights_equat_shell.size(); i++) { 
    301                 dp.equat_shell = weights_equat_shell[i].value; 
    302                 for(int k=0; k< (int)weights_polar_shell.size(); k++) { 
    303                         dp.polar_shell = weights_polar_shell[k].value; 
    304                         //Note: output of "DiamEllip(dp.polar_shell,dp.equat_shell)" is DIAMETER. 
    305                         sum +=weights_equat_shell[i].weight 
    306                                 * weights_polar_shell[k].weight*DiamEllip(dp.polar_shell,dp.equat_shell)/2.0; 
    307                         norm += weights_equat_shell[i].weight* weights_polar_shell[k].weight; 
    308                 } 
    309         } 
    310         if (norm != 0){ 
    311                 //return the averaged value 
    312                 rad_out =  sum/norm;} 
    313         else{ 
    314                 //return normal value 
    315                 //Note: output of "DiamEllip(dp.polar_shell,dp.equat_shell)" is DIAMETER. 
    316                 rad_out = DiamEllip(dp.polar_shell,dp.equat_shell)/2.0;} 
    317  
    318         return rad_out; 
    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  
    2323 
    2424#include <math.h> 
    25 #include "models.hh" 
    2625#include "parameters.hh" 
    2726#include <stdio.h> 
    2827using namespace std; 
     28#include "stacked_disks.h" 
    2929 
    3030extern "C" { 
    31         #include "libCylinder.h" 
    32         #include "libStructureFactor.h" 
    33         #include "stacked_disks.h" 
     31#include "libCylinder.h" 
     32#include "libStructureFactor.h" 
     33} 
     34 
     35typedef 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 */ 
     59static 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 */ 
     122static 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); 
    34126} 
    35127 
    36128StackedDisksModel :: StackedDisksModel() { 
    37         scale      = Parameter(1.0); 
    38         radius     = Parameter(3000.0, true); 
    39         radius.set_min(0.0); 
    40         core_thick  = Parameter(10.0, true); 
    41         core_thick.set_min(0.0); 
    42         layer_thick     = Parameter(15.0); 
    43         layer_thick.set_min(0.0); 
    44         core_sld = Parameter(4.0e-6); 
    45         layer_sld  = Parameter(-4.0e-7); 
    46         solvent_sld  = Parameter(5.0e-6); 
    47         n_stacking   = Parameter(1); 
    48         sigma_d   = Parameter(0); 
    49         background = Parameter(0.001); 
    50         axis_theta  = Parameter(0.0, true); 
    51         axis_phi    = Parameter(0.0, true); 
     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); 
    52144} 
    53145 
     
    59151 */ 
    60152double StackedDisksModel :: operator()(double q) { 
    61         double dp[10]; 
    62  
    63         // Fill parameter array for IGOR library 
    64         // Add the background after averaging 
    65         dp[0] = scale(); 
    66         dp[1] = radius(); 
    67         dp[2] = core_thick(); 
    68         dp[3] = layer_thick(); 
    69         dp[4] = core_sld(); 
    70         dp[5] = layer_sld(); 
    71         dp[6] = solvent_sld(); 
    72         dp[7] = n_stacking(); 
    73         dp[8] = sigma_d(); 
    74         dp[9] = 0.0; 
    75  
    76         // Get the dispersion points for the radius 
    77         vector<WeightPoint> weights_radius; 
    78         radius.get_weights(weights_radius); 
    79  
    80         // Get the dispersion points for the core_thick 
    81         vector<WeightPoint> weights_core_thick; 
    82         core_thick.get_weights(weights_core_thick); 
    83  
    84         // Get the dispersion points for the layer_thick 
    85         vector<WeightPoint> weights_layer_thick; 
    86         layer_thick.get_weights(weights_layer_thick); 
    87  
    88         // Perform the computation, with all weight points 
    89         double sum = 0.0; 
    90         double norm = 0.0; 
    91         double vol = 0.0; 
    92  
    93         // Loop over length weight points 
    94         for(int i=0; i< (int)weights_radius.size(); i++) { 
    95                 dp[1] = weights_radius[i].value; 
    96  
    97                 // Loop over radius weight points 
    98                 for(int j=0; j< (int)weights_core_thick.size(); j++) { 
    99                         dp[2] = weights_core_thick[j].value; 
    100  
    101                         // Loop over thickness weight points 
    102                         for(int k=0; k< (int)weights_layer_thick.size(); k++) { 
    103                                 dp[3] = weights_layer_thick[k].value; 
    104                                 //Un-normalize by volume 
    105                                 sum += weights_radius[i].weight 
    106                                         * weights_core_thick[j].weight * weights_layer_thick[k].weight* StackedDiscs(dp, q) 
    107                                         *pow(weights_radius[i].value,2)*(weights_core_thick[j].value+2*weights_layer_thick[k].value); 
    108                                 //Find average volume 
    109                                 vol += weights_radius[i].weight 
    110                                         * weights_core_thick[j].weight * weights_layer_thick[k].weight 
    111                                         *pow(weights_radius[i].value,2)*(weights_core_thick[j].value+2*weights_layer_thick[k].value); 
    112                                 norm += weights_radius[i].weight 
    113                                         * weights_core_thick[j].weight* weights_layer_thick[k].weight; 
    114                         } 
    115                 } 
    116         } 
    117         if (vol != 0.0 && norm != 0.0) { 
    118                 //Re-normalize by avg volume 
    119                 sum = sum/(vol/norm);} 
    120  
    121         return sum/norm + background(); 
     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(); 
    122214} 
    123215 
     
    129221 */ 
    130222double StackedDisksModel :: operator()(double qx, double qy) { 
    131         StackedDisksParameters dp; 
    132         // Fill parameter array 
    133         dp.scale      = scale(); 
    134         dp.core_thick    = core_thick(); 
    135         dp.radius         = radius(); 
    136         dp.layer_thick  = layer_thick(); 
    137         dp.core_sld   = core_sld(); 
    138         dp.layer_sld  = layer_sld(); 
    139         dp.solvent_sld= solvent_sld(); 
    140         dp.n_stacking     = n_stacking(); 
    141         dp.sigma_d   = sigma_d(); 
    142         dp.background = 0.0; 
    143         dp.axis_theta = axis_theta(); 
    144         dp.axis_phi   = axis_phi(); 
    145  
    146         // Get the dispersion points for the length 
    147         vector<WeightPoint> weights_core_thick; 
    148         core_thick.get_weights(weights_core_thick); 
    149  
    150         // Get the dispersion points for the radius 
    151         vector<WeightPoint> weights_radius; 
    152         radius.get_weights(weights_radius); 
    153  
    154         // Get the dispersion points for the thickness 
    155         vector<WeightPoint> weights_layer_thick; 
    156         layer_thick.get_weights(weights_layer_thick); 
    157  
    158         // Get angular averaging for theta 
    159         vector<WeightPoint> weights_theta; 
    160         axis_theta.get_weights(weights_theta); 
    161  
    162         // Get angular averaging for phi 
    163         vector<WeightPoint> weights_phi; 
    164         axis_phi.get_weights(weights_phi); 
    165  
    166         // Perform the computation, with all weight points 
    167         double sum = 0.0; 
    168         double norm = 0.0; 
    169         double norm_vol = 0.0; 
    170         double vol = 0.0; 
    171  
    172         // Loop over length weight points 
    173         for(int i=0; i< (int)weights_core_thick.size(); i++) { 
    174                 dp.core_thick = weights_core_thick[i].value; 
    175  
    176                 // Loop over radius weight points 
    177                 for(int j=0; j< (int)weights_radius.size(); j++) { 
    178                         dp.radius = weights_radius[j].value; 
    179  
    180                                 // Loop over thickness weight points 
    181                                 for(int k=0; k< (int)weights_layer_thick.size(); k++) { 
    182                                 dp.layer_thick = weights_layer_thick[k].value; 
    183  
    184                                         for(int l=0; l< (int)weights_theta.size(); l++) { 
    185                                         dp.axis_theta = weights_theta[l].value; 
    186  
    187                                                 // Average over phi distribution 
    188                                                 for(int m=0; m <(int)weights_phi.size(); m++) { 
    189                                                         dp.axis_phi = weights_phi[m].value; 
    190  
    191                                                         //Un-normalize by volume 
    192                                                         double _ptvalue = weights_core_thick[i].weight 
    193                                                                 * weights_radius[j].weight 
    194                                                                 * weights_layer_thick[k].weight 
    195                                                                 * weights_theta[l].weight 
    196                                                                 * weights_phi[m].weight 
    197                                                                 * stacked_disks_analytical_2DXY(&dp, qx, qy) 
    198                                                                 *pow(weights_radius[j].value,2)*(weights_core_thick[i].value+2*weights_layer_thick[k].value); 
    199                                                         if (weights_theta.size()>1) { 
    200                                                                 _ptvalue *= fabs(sin(weights_theta[l].value)); 
    201                                                         } 
    202                                                         sum += _ptvalue; 
    203                                                         //Find average volume 
    204                                                         vol += weights_radius[j].weight 
    205                                                                 * weights_core_thick[i].weight * weights_layer_thick[k].weight 
    206                                                                 *pow(weights_radius[j].value,2)*(weights_core_thick[i].value+2*weights_layer_thick[k].value); 
    207                                                         //Find norm for volume 
    208                                                         norm_vol += weights_radius[j].weight 
    209                                                                 * weights_core_thick[i].weight * weights_layer_thick[k].weight; 
    210  
    211                                                         norm += weights_core_thick[i].weight 
    212                                                                 * weights_radius[j].weight 
    213                                                                 * weights_layer_thick[k].weight 
    214                                                                 * weights_theta[l].weight 
    215                                                                 * weights_phi[m].weight; 
    216                                                 } 
    217                                 } 
    218                         } 
    219                 } 
    220         } 
    221         // Averaging in theta needs an extra normalization 
    222         // factor to account for the sin(theta) term in the 
    223         // integration (see documentation). 
    224         if (weights_theta.size()>1) norm = norm / asin(1.0); 
    225         if (vol != 0.0 && norm_vol != 0.0) { 
    226                 //Re-normalize by avg volume 
    227                 sum = sum/(vol/norm_vol);} 
    228         return sum/norm + background(); 
     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(); 
    229321} 
    230322 
     
    237329 */ 
    238330double StackedDisksModel :: evaluate_rphi(double q, double phi) { 
    239         double qx = q*cos(phi); 
    240         double qy = q*sin(phi); 
    241         return (*this).operator()(qx, qy); 
     331  double qx = q*cos(phi); 
     332  double qy = q*sin(phi); 
     333  return (*this).operator()(qx, qy); 
    242334} 
    243335/** 
     
    246338 */ 
    247339double StackedDisksModel :: calculate_ER() { 
    248         StackedDisksParameters dp; 
    249  
    250         dp.core_thick    = core_thick(); 
    251         dp.radius         = radius(); 
    252         dp.layer_thick  = layer_thick(); 
    253         dp.n_stacking     = n_stacking(); 
    254  
    255         double rad_out = 0.0; 
    256         if (dp.n_stacking <= 0.0){ 
    257                 return rad_out; 
    258         } 
    259  
    260         // Perform the computation, with all weight points 
    261         double sum = 0.0; 
    262         double norm = 0.0; 
    263  
    264         // Get the dispersion points for the length 
    265         vector<WeightPoint> weights_core_thick; 
    266         core_thick.get_weights(weights_core_thick); 
    267  
    268         // Get the dispersion points for the radius 
    269         vector<WeightPoint> weights_radius; 
    270         radius.get_weights(weights_radius); 
    271  
    272         // Get the dispersion points for the thickness 
    273         vector<WeightPoint> weights_layer_thick; 
    274         layer_thick.get_weights(weights_layer_thick); 
    275  
    276         // Loop over major shell weight points 
    277         for(int i=0; i< (int)weights_core_thick.size(); i++) { 
    278                 dp.core_thick = weights_core_thick[i].value; 
    279                 for(int j=0; j< (int)weights_layer_thick.size(); j++) { 
    280                         dp.layer_thick = weights_layer_thick[j].value; 
    281                         for(int k=0; k< (int)weights_radius.size(); k++) { 
    282                                 dp.radius = weights_radius[k].value; 
    283                                 //Note: output of "DiamCyl(dp.length,dp.radius)" is DIAMETER. 
    284                                 sum +=weights_core_thick[i].weight*weights_layer_thick[j].weight 
    285                                         * weights_radius[k].weight*DiamCyl(dp.n_stacking*(dp.layer_thick*2.0+dp.core_thick),dp.radius)/2.0; 
    286                                 norm += weights_core_thick[i].weight*weights_layer_thick[j].weight* weights_radius[k].weight; 
    287                         } 
    288                 } 
    289         } 
    290         if (norm != 0){ 
    291                 //return the averaged value 
    292                 rad_out =  sum/norm;} 
    293         else{ 
    294                 //return normal value 
    295                 //Note: output of "DiamCyl(dp.length,dp.radius)" is DIAMETER. 
    296                 rad_out = DiamCyl(dp.n_stacking*(dp.layer_thick*2.0+dp.core_thick),dp.radius)/2.0;} 
    297  
    298         return rad_out; 
    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  
    1818 *   sansmodels/src/libigor 
    1919 * 
    20  *      TODO: refactor so that we pull in the old sansmodels.c_extensions 
    2120 */ 
    2221 
    2322#include <math.h> 
    24 #include "models.hh" 
    2523#include "parameters.hh" 
    2624#include <stdio.h> 
     25#include <stdlib.h> 
    2726using namespace std; 
     27#include "triaxial_ellipsoid.h" 
    2828 
    2929extern "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 
     34typedef 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 
     48static 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 */ 
     74static 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 */ 
     153static 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 
    34160 
    35161TriaxialEllipsoidModel :: TriaxialEllipsoidModel() { 
    36         scale      = Parameter(1.0); 
    37         semi_axisA     = Parameter(35.0, true); 
    38         semi_axisA.set_min(0.0); 
    39         semi_axisB     = Parameter(100.0, true); 
    40         semi_axisB.set_min(0.0); 
    41         semi_axisC  = Parameter(400.0, true); 
    42         semi_axisC.set_min(0.0); 
    43         sldEll   = Parameter(1.0e-6); 
    44         sldSolv   = Parameter(6.3e-6); 
    45         background = Parameter(0.0); 
    46         axis_theta  = Parameter(57.325, true); 
    47         axis_phi    = Parameter(57.325, true); 
    48         axis_psi    = Parameter(0.0, true); 
     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); 
    49175} 
    50176 
     
    56182 */ 
    57183double TriaxialEllipsoidModel :: operator()(double q) { 
    58         double dp[7]; 
    59  
    60         // Fill parameter array for IGOR library 
    61         // Add the background after averaging 
    62         dp[0] = scale(); 
    63         dp[1] = semi_axisA(); 
    64         dp[2] = semi_axisB(); 
    65         dp[3] = semi_axisC(); 
    66         dp[4] = sldEll(); 
    67         dp[5] = sldSolv(); 
    68         dp[6] = 0.0; 
    69  
    70         // Get the dispersion points for the semi axis A 
    71         vector<WeightPoint> weights_semi_axisA; 
    72         semi_axisA.get_weights(weights_semi_axisA); 
    73  
    74         // Get the dispersion points for the semi axis B 
    75         vector<WeightPoint> weights_semi_axisB; 
    76         semi_axisB.get_weights(weights_semi_axisB); 
    77  
    78         // Get the dispersion points for the semi axis C 
    79         vector<WeightPoint> weights_semi_axisC; 
    80         semi_axisC.get_weights(weights_semi_axisC); 
    81  
    82         // Perform the computation, with all weight points 
    83         double sum = 0.0; 
    84         double norm = 0.0; 
    85         double vol = 0.0; 
    86  
    87         // Loop over semi axis A weight points 
    88         for(int i=0; i< (int)weights_semi_axisA.size(); i++) { 
    89                 dp[1] = weights_semi_axisA[i].value; 
    90  
    91                 // Loop over semi axis B weight points 
    92                 for(int j=0; j< (int)weights_semi_axisB.size(); j++) { 
    93                         dp[2] = weights_semi_axisB[j].value; 
    94  
    95                         // Loop over semi axis C weight points 
    96                         for(int k=0; k< (int)weights_semi_axisC.size(); k++) { 
    97                                 dp[3] = weights_semi_axisC[k].value; 
    98                                 //Un-normalize  by volume 
    99                                 sum += weights_semi_axisA[i].weight 
    100                                         * weights_semi_axisB[j].weight * weights_semi_axisC[k].weight* TriaxialEllipsoid(dp, q) 
    101                                         * weights_semi_axisA[i].value*weights_semi_axisB[j].value*weights_semi_axisC[k].value; 
    102                                 //Find average volume 
    103                                 vol += weights_semi_axisA[i].weight 
    104                                         * weights_semi_axisB[j].weight * weights_semi_axisC[k].weight 
    105                                         * weights_semi_axisA[i].value*weights_semi_axisB[j].value*weights_semi_axisC[k].value; 
    106  
    107                                 norm += weights_semi_axisA[i].weight 
    108                                         * weights_semi_axisB[j].weight * weights_semi_axisC[k].weight; 
    109                         } 
    110                 } 
    111         } 
    112         if (vol != 0.0 && norm != 0.0) { 
    113                 //Re-normalize by avg volume 
    114                 sum = sum/(vol/norm);} 
    115  
    116         return sum/norm + background(); 
     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(); 
    117243} 
    118244 
     
    124250 */ 
    125251double TriaxialEllipsoidModel :: operator()(double qx, double qy) { 
    126         TriaxialEllipsoidParameters dp; 
    127         // Fill parameter array 
    128         dp.scale      = scale(); 
    129         dp.semi_axisA   = semi_axisA(); 
    130         dp.semi_axisB     = semi_axisB(); 
    131         dp.semi_axisC     = semi_axisC(); 
    132         dp.sldEll   = sldEll(); 
    133         dp.sldSolv   = sldSolv(); 
    134         dp.background = 0.0; 
    135         dp.axis_theta  = axis_theta(); 
    136         dp.axis_phi    = axis_phi(); 
    137         dp.axis_psi    = axis_psi(); 
    138  
    139         // Get the dispersion points for the semi_axis A 
    140         vector<WeightPoint> weights_semi_axisA; 
    141         semi_axisA.get_weights(weights_semi_axisA); 
    142  
    143         // Get the dispersion points for the semi_axis B 
    144         vector<WeightPoint> weights_semi_axisB; 
    145         semi_axisB.get_weights(weights_semi_axisB); 
    146  
    147         // Get the dispersion points for the semi_axis C 
    148         vector<WeightPoint> weights_semi_axisC; 
    149         semi_axisC.get_weights(weights_semi_axisC); 
    150  
    151         // Get angular averaging for theta 
    152         vector<WeightPoint> weights_theta; 
    153         axis_theta.get_weights(weights_theta); 
    154  
    155         // Get angular averaging for phi 
    156         vector<WeightPoint> weights_phi; 
    157         axis_phi.get_weights(weights_phi); 
    158  
    159         // Get angular averaging for psi 
    160         vector<WeightPoint> weights_psi; 
    161         axis_psi.get_weights(weights_psi); 
    162  
    163         // Perform the computation, with all weight points 
    164         double sum = 0.0; 
    165         double norm = 0.0; 
    166         double norm_vol = 0.0; 
    167         double vol = 0.0; 
    168         double pi = 4.0*atan(1.0); 
    169         // Loop over semi axis A weight points 
    170         for(int i=0; i< (int)weights_semi_axisA.size(); i++) { 
    171                 dp.semi_axisA = weights_semi_axisA[i].value; 
    172  
    173                 // Loop over semi axis B weight points 
    174                 for(int j=0; j< (int)weights_semi_axisB.size(); j++) { 
    175                         dp.semi_axisB = weights_semi_axisB[j].value; 
    176  
    177                         // Loop over semi axis C weight points 
    178                         for(int k=0; k < (int)weights_semi_axisC.size(); k++) { 
    179                         dp.semi_axisC = weights_semi_axisC[k].value; 
    180  
    181                                 // Average over theta distribution 
    182                                 for(int l=0; l< (int)weights_theta.size(); l++) { 
    183                                         dp.axis_theta = weights_theta[l].value; 
    184  
    185                                         // Average over phi distribution 
    186                                         for(int m=0; m <(int)weights_phi.size(); m++) { 
    187                                                 dp.axis_phi = weights_phi[m].value; 
    188                                                 // Average over psi distribution 
    189                                                 for(int n=0; n <(int)weights_psi.size(); n++) { 
    190                                                         dp.axis_psi = weights_psi[n].value; 
    191                                                         //Un-normalize  by volume 
    192                                                         double _ptvalue = weights_semi_axisA[i].weight 
    193                                                                 * weights_semi_axisB[j].weight 
    194                                                                 * weights_semi_axisC[k].weight 
    195                                                                 * weights_theta[l].weight 
    196                                                                 * weights_phi[m].weight 
    197                                                                 * weights_psi[n].weight 
    198                                                                 * triaxial_ellipsoid_analytical_2DXY(&dp, qx, qy) 
    199                                                                 * weights_semi_axisA[i].value*weights_semi_axisB[j].value*weights_semi_axisC[k].value; 
    200                                                         if (weights_theta.size()>1) { 
    201                                                                 _ptvalue *= fabs(sin(weights_theta[k].value*pi/180.0)); 
    202                                                         } 
    203                                                         sum += _ptvalue; 
    204                                                         //Find average volume 
    205                                                         vol += weights_semi_axisA[i].weight 
    206                                                                 * weights_semi_axisB[j].weight 
    207                                                                 * weights_semi_axisC[k].weight 
    208                                                                 * weights_semi_axisA[i].value*weights_semi_axisB[j].value*weights_semi_axisC[k].value; 
    209                                                         //Find norm for volume 
    210                                                         norm_vol += weights_semi_axisA[i].weight 
    211                                                                 * weights_semi_axisB[j].weight 
    212                                                                 * weights_semi_axisC[k].weight; 
    213  
    214                                                         norm += weights_semi_axisA[i].weight 
    215                                                                 * weights_semi_axisB[j].weight 
    216                                                                 * weights_semi_axisC[k].weight 
    217                                                                 * weights_theta[l].weight 
    218                                                                 * weights_phi[m].weight 
    219                                                                 * weights_psi[n].weight; 
    220                                                 } 
    221                                         } 
    222  
    223                                 } 
    224                         } 
    225                 } 
    226         } 
    227         // Averaging in theta needs an extra normalization 
    228         // factor to account for the sin(theta) term in the 
    229         // integration (see documentation). 
    230         if (weights_theta.size()>1) norm = norm / asin(1.0); 
    231  
    232         if (vol != 0.0 && norm_vol != 0.0) { 
    233                 //Re-normalize by avg volume 
    234                 sum = sum/(vol/norm_vol);} 
    235  
    236         return sum/norm + background(); 
     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(); 
    237363} 
    238364 
     
    245371 */ 
    246372double TriaxialEllipsoidModel :: evaluate_rphi(double q, double phi) { 
    247         double qx = q*cos(phi); 
    248         double qy = q*sin(phi); 
    249         return (*this).operator()(qx, qy); 
     373  double qx = q*cos(phi); 
     374  double qy = q*sin(phi); 
     375  return (*this).operator()(qx, qy); 
    250376} 
    251377/** 
     
    254380 */ 
    255381double TriaxialEllipsoidModel :: calculate_ER() { 
    256         TriaxialEllipsoidParameters dp; 
    257  
    258         dp.semi_axisA   = semi_axisA(); 
    259         dp.semi_axisB     = semi_axisB(); 
    260         //polar axis C 
    261         dp.semi_axisC     = semi_axisC(); 
    262  
    263         double rad_out = 0.0; 
    264         //Surface average radius at the equat. cross section. 
    265         double suf_rad = sqrt(dp.semi_axisA * dp.semi_axisB); 
    266  
    267         // Perform the computation, with all weight points 
    268         double sum = 0.0; 
    269         double norm = 0.0; 
    270  
    271         // Get the dispersion points for the semi_axis A 
    272         vector<WeightPoint> weights_semi_axisA; 
    273         semi_axisA.get_weights(weights_semi_axisA); 
    274  
    275         // Get the dispersion points for the semi_axis B 
    276         vector<WeightPoint> weights_semi_axisB; 
    277         semi_axisB.get_weights(weights_semi_axisB); 
    278  
    279         // Get the dispersion points for the semi_axis C 
    280         vector<WeightPoint> weights_semi_axisC; 
    281         semi_axisC.get_weights(weights_semi_axisC); 
    282  
    283         // Loop over semi axis A weight points 
    284         for(int i=0; i< (int)weights_semi_axisA.size(); i++) { 
    285                 dp.semi_axisA = weights_semi_axisA[i].value; 
    286  
    287                 // Loop over semi axis B weight points 
    288                 for(int j=0; j< (int)weights_semi_axisB.size(); j++) { 
    289                         dp.semi_axisB = weights_semi_axisB[j].value; 
    290  
    291                         // Loop over semi axis C weight points 
    292                         for(int k=0; k < (int)weights_semi_axisC.size(); k++) { 
    293                                 dp.semi_axisC = weights_semi_axisC[k].value; 
    294  
    295                                 //Calculate surface averaged radius 
    296                                 suf_rad = sqrt(dp.semi_axisA * dp.semi_axisB); 
    297  
    298                                 //Sum 
    299                                 sum += weights_semi_axisA[i].weight 
    300                                         * weights_semi_axisB[j].weight 
    301                                         * weights_semi_axisC[k].weight * DiamEllip(dp.semi_axisC, suf_rad)/2.0; 
    302                                 //Norm 
    303                                 norm += weights_semi_axisA[i].weight* weights_semi_axisB[j].weight 
    304                                         * weights_semi_axisC[k].weight; 
    305                         } 
    306                 } 
    307         } 
    308         if (norm != 0){ 
    309                 //return the averaged value 
    310                 rad_out =  sum/norm;} 
    311         else{ 
    312                 //return normal value 
    313                 rad_out = DiamEllip(dp.semi_axisC, suf_rad)/2.0;} 
    314  
    315         return rad_out; 
    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  
    2121 
    2222#include <math.h> 
    23 #include "models.hh" 
    2423#include "parameters.hh" 
    2524#include <stdio.h> 
    2625using namespace std; 
     26#include "vesicle.h" 
    2727 
    2828extern "C" { 
    29         #include "libSphere.h" 
    30         #include "vesicle.h" 
     29#include "libSphere.h" 
    3130} 
    3231 
     32typedef struct { 
     33  double scale; 
     34  double radius; 
     35  double thickness; 
     36  double core_sld; 
     37  double shell_sld; 
     38  double background; 
     39} VesicleParameters; 
     40 
    3341VesicleModel :: VesicleModel() { 
    34         scale      = Parameter(1.0); 
    35         radius     = Parameter(100.0, true); 
    36         radius.set_min(0.0); 
    37         thickness  = Parameter(30.0, true); 
    38         thickness.set_min(0.0); 
    39         core_sld   = Parameter(6.36e-6); 
    40         shell_sld   = Parameter(5.0e-7); 
    41         background = Parameter(0.0); 
     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); 
    4250} 
    4351 
     
    4957 */ 
    5058double VesicleModel :: operator()(double q) { 
    51         double dp[6]; 
     59  double dp[6]; 
    5260 
    53         // Fill parameter array for IGOR library 
    54         // Add the background after averaging 
    55         dp[0] = scale(); 
    56         dp[1] = radius(); 
    57         dp[2] = thickness(); 
    58         dp[3] = core_sld(); 
    59         dp[4] = shell_sld(); 
    60         dp[5] = 0.0; 
     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; 
    6169 
    6270 
    63         // Get the dispersion points for the core radius 
    64         vector<WeightPoint> weights_radius; 
    65         radius.get_weights(weights_radius); 
    66         // Get the dispersion points for the thickness 
    67         vector<WeightPoint> weights_thickness; 
    68         thickness.get_weights(weights_thickness); 
     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); 
    6977 
    70         // Perform the computation, with all weight points 
    71         double sum = 0.0; 
    72         double norm = 0.0; 
    73         double vol = 0.0; 
     78  // Perform the computation, with all weight points 
     79  double sum = 0.0; 
     80  double norm = 0.0; 
     81  double vol = 0.0; 
    7482 
    75         // Loop over radius weight points 
    76         for(int i=0; i< (int)weights_radius.size(); i++) { 
    77                 dp[1] = weights_radius[i].value; 
    78                 for(int j=0; j< (int)weights_thickness.size(); j++) { 
    79                         dp[2] = weights_thickness[j].value; 
    80                         sum += weights_radius[i].weight 
    81                                 * weights_thickness[j].weight * VesicleForm(dp, q) 
    82                                 *(pow(weights_radius[i].value+weights_thickness[j].value,3)-pow(weights_radius[i].value,3)); 
    83                         //Find average volume 
    84                         vol += weights_radius[i].weight * weights_thickness[j].weight 
    85                                 *(pow(weights_radius[i].value+weights_thickness[j].value,3)-pow(weights_radius[i].value,3)); 
    86                         norm += weights_radius[i].weight * weights_thickness[j].weight; 
    87                 } 
    88         } 
    89         if (vol != 0.0 && norm != 0.0) { 
    90                 //Re-normalize by avg volume 
    91                 sum = sum/(vol/norm);} 
     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);} 
    92100 
    93         return sum/norm + background(); 
     101  return sum/norm + background(); 
    94102} 
    95103 
     
    101109 */ 
    102110double VesicleModel :: operator()(double qx, double qy) { 
    103         double q = sqrt(qx*qx + qy*qy); 
    104         return (*this).operator()(q); 
     111  double q = sqrt(qx*qx + qy*qy); 
     112  return (*this).operator()(q); 
    105113} 
    106114 
     
    113121 */ 
    114122double VesicleModel :: evaluate_rphi(double q, double phi) { 
    115         return (*this).operator()(q); 
     123  return (*this).operator()(q); 
    116124} 
    117125/** 
     
    120128 */ 
    121129double VesicleModel :: calculate_ER() { 
    122         VesicleParameters dp; 
     130  VesicleParameters dp; 
    123131 
    124         dp.radius     = radius(); 
    125         dp.thickness  = thickness(); 
     132  dp.radius     = radius(); 
     133  dp.thickness  = thickness(); 
    126134 
    127         double rad_out = 0.0; 
     135  double rad_out = 0.0; 
    128136 
    129         // Perform the computation, with all weight points 
    130         double sum = 0.0; 
    131         double norm = 0.0; 
     137  // Perform the computation, with all weight points 
     138  double sum = 0.0; 
     139  double norm = 0.0; 
    132140 
    133141 
    134         // Get the dispersion points for the major shell 
    135         vector<WeightPoint> weights_thickness; 
    136         thickness.get_weights(weights_thickness); 
     142  // Get the dispersion points for the major shell 
     143  vector<WeightPoint> weights_thickness; 
     144  thickness.get_weights(weights_thickness); 
    137145 
    138         // Get the dispersion points for the minor shell 
    139         vector<WeightPoint> weights_radius ; 
    140         radius.get_weights(weights_radius); 
     146  // Get the dispersion points for the minor shell 
     147  vector<WeightPoint> weights_radius ; 
     148  radius.get_weights(weights_radius); 
    141149 
    142         // Loop over major shell weight points 
    143         for(int j=0; j< (int)weights_thickness.size(); j++) { 
    144                 dp.thickness = weights_thickness[j].value; 
    145                 for(int k=0; k< (int)weights_radius.size(); k++) { 
    146                         dp.radius = weights_radius[k].value; 
    147                         sum += weights_thickness[j].weight 
    148                                 * weights_radius[k].weight*(dp.radius+dp.thickness); 
    149                         norm += weights_thickness[j].weight* weights_radius[k].weight; 
    150                 } 
    151         } 
    152         if (norm != 0){ 
    153                 //return the averaged value 
    154                 rad_out =  sum/norm;} 
    155         else{ 
    156                 //return normal value 
    157                 rad_out = (dp.radius+dp.thickness);} 
     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);} 
    158166 
    159         return rad_out; 
     167  return rad_out; 
    160168} 
Note: See TracChangeset for help on using the changeset viewer.