Ignore:
Timestamp:
Mar 1, 2016 7:31:49 PM (8 years ago)
Author:
Paul Kienzle <pkienzle@…>
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:
4adf48e
Parents:
792e6be
Message:

fix 2D barbell model and add it to the fit page

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/sas/models/c_extension/c_models/barbell.cpp

    r79492222 rdb46d13  
    3030        #include "barbell.h" 
    3131} 
     32 
     33// Convenience parameter structure 
     34typedef struct { 
     35    double scale; 
     36    double rad_bar; 
     37    double len_bar; 
     38    double rad_bell; 
     39    double sld_barbell; 
     40    double sld_solv; 
     41    double background; 
     42    double theta; 
     43    double phi; 
     44} BarBellParameters; 
    3245 
    3346BarBellModel :: BarBellModel() { 
     
    4659} 
    4760 
    48 double bar2d_kernel(double dp[], double q, double alpha) { 
     61double barbell2d_kernel(double dp[], double q, double alpha) { 
    4962  int j; 
    5063  double Pi; 
     
    113126  return answer; 
    114127} 
     128 
     129/** 
     130 * Function to evaluate 2D scattering function 
     131 * @param pars: parameters of the BarBell 
     132 * @param q: q-value 
     133 * @param q_x: q_x / q 
     134 * @param q_y: q_y / q 
     135 * @return: function value 
     136 */ 
     137static double barbell_analytical_2D_scaled(BarBellParameters *pars, double q, double q_x, double q_y) { 
     138  double cyl_x, cyl_y;//, cyl_z; 
     139  //double q_z; 
     140  double alpha, cos_val; 
     141  double answer; 
     142  double dp[7]; 
     143  //convert angle degree to radian 
     144  double pi = 4.0*atan(1.0); 
     145  double theta = pars->theta * pi/180.0; 
     146  double phi = pars->phi * pi/180.0; 
     147 
     148  dp[0] = pars->scale; 
     149  dp[1] = pars->rad_bar; 
     150  dp[2] = pars->len_bar; 
     151  dp[3] = pars->rad_bell; 
     152  dp[4] = pars->sld_barbell; 
     153  dp[5] = pars->sld_solv; 
     154  dp[6] = pars->background; 
     155 
     156 
     157  //double Pi = 4.0*atan(1.0); 
     158    // Cylinder orientation 
     159    cyl_x = cos(theta) * cos(phi); 
     160    cyl_y = sin(theta); 
     161    //cyl_z = -cos(theta) * sin(phi); 
     162 
     163    // q vector 
     164    //q_z = 0; 
     165 
     166    // Compute the angle btw vector q and the 
     167    // axis of the cylinder 
     168    cos_val = cyl_x*q_x + cyl_y*q_y;// + cyl_z*q_z; 
     169 
     170    // The following test should always pass 
     171    if (fabs(cos_val)>1.0) { 
     172      printf("cyl_ana_2D: Unexpected error: cos(alpha)>1\n"); 
     173      return 0; 
     174    } 
     175 
     176    // Note: cos(alpha) = 0 and 1 will get an 
     177    // undefined value from CylKernel 
     178  alpha = acos( cos_val ); 
     179 
     180  answer = barbell2d_kernel(dp, q, alpha); 
     181 
     182 
     183  return answer; 
     184 
     185} 
     186 
     187/** 
     188 * Function to evaluate 2D scattering function 
     189 * @param pars: parameters of the BarBell 
     190 * @param q: q-value 
     191 * @return: function value 
     192 */ 
     193static double barbell_analytical_2DXY(BarBellParameters *pars, double qx, double qy){ 
     194  double q; 
     195  q = sqrt(qx*qx+qy*qy); 
     196  return barbell_analytical_2D_scaled(pars, q, qx/q, qy/q); 
     197} 
     198 
    115199/** 
    116200 * Function to evaluate 1D scattering function 
     
    190274 */ 
    191275double BarBellModel :: operator()(double qx, double qy) { 
    192   double dp[7]; 
    193  
    194   // Fill parameter array for IGOR library 
    195   // Add the background after averaging 
    196   dp[0] = scale(); 
    197   dp[1] = rad_bar(); 
    198   dp[2] = len_bar(); 
    199   dp[3] = rad_bell(); 
    200   dp[4] = sld_barbell(); 
    201   dp[5] = sld_solv(); 
    202   dp[6] = 0.0; 
    203  
    204   double _theta = theta(); 
    205   double _phi = phi(); 
     276  BarBellParameters dp; 
     277 
     278        // Fill parameter array for IGOR library 
     279        // Add the background after averaging 
     280        dp.scale = scale(); 
     281        dp.rad_bar = rad_bar(); 
     282        dp.len_bar = len_bar(); 
     283        dp.rad_bell = rad_bell(); 
     284        dp.sld_barbell = sld_barbell(); 
     285        dp.sld_solv = sld_solv(); 
     286        dp.background = 0.0; 
     287        dp.theta = theta(); 
     288        dp.phi = phi(); 
    206289 
    207290        // Get the dispersion points for the rad_bar 
     
    237320        // Loop over radius weight points 
    238321        for(size_t i=0; i<weights_rad_bar.size(); i++) { 
    239                 dp[1] = weights_rad_bar[i].value; 
     322                dp.rad_bar = weights_rad_bar[i].value; 
    240323                for(size_t j=0; j<weights_len_bar.size(); j++) { 
    241                         dp[2] = weights_len_bar[j].value; 
     324                        dp.len_bar = weights_len_bar[j].value; 
    242325                        for(size_t k=0; k<weights_rad_bell.size(); k++) { 
    243                                 dp[3] = weights_rad_bell[k].value; 
     326                                dp.rad_bell = weights_rad_bell[k].value; 
    244327                                // Average over theta distribution 
    245328                                for(size_t l=0; l< weights_theta.size(); l++) { 
    246                                         _theta = weights_theta[l].value; 
     329                                        dp.theta = weights_theta[l].value; 
    247330                                        // Average over phi distribution 
    248331                                        for(size_t m=0; m< weights_phi.size(); m++) { 
    249                                                 _phi = weights_phi[m].value; 
     332                                                dp.phi = weights_phi[m].value; 
    250333                                                //Un-normalize Form by volume 
    251                                                 hDist = sqrt(fabs(dp[3]*dp[3]-dp[1]*dp[1])); 
    252                                                 vol_i = pi*dp[1]*dp[1]*dp[2]+2.0*pi*(2.0*dp[3]*dp[3]*dp[3]/3.0 
    253                                                                                 +dp[3]*dp[3]*hDist-hDist*hDist*hDist/3.0); 
    254  
    255                                           const double q = sqrt(qx*qx+qy*qy); 
    256                                           //convert angle degree to radian 
    257                                           const double pi = 4.0*atan(1.0); 
    258  
    259                                           // Cylinder orientation 
    260                                     const double cyl_x = cos(_theta * pi/180.0) * cos(_phi * pi/180.0); 
    261                                     const double cyl_y = sin(_theta * pi/180.0); 
    262  
    263                                     // Compute the angle btw vector q and the 
    264                                     // axis of the cylinder (assume qz = 0) 
    265                                     const double cos_val = cyl_x*qx + cyl_y*qy; 
    266  
    267                                     // The following test should always pass 
    268                                     if (fabs(cos_val)>1.0) { 
    269                                       return 0; 
    270                                     } 
    271  
    272                                     // Note: cos(alpha) = 0 and 1 will get an 
    273                                     // undefined value from CylKernel 
    274                                     const double alpha = acos( cos_val ); 
    275  
    276             // Call the IGOR library function to get the kernel 
    277             const double output = bar2d_kernel(dp, q, alpha)/sin(alpha); 
    278  
     334                                                hDist = -sqrt(fabs(dp.rad_bell*dp.rad_bell-dp.rad_bar*dp.rad_bar)); 
     335                                                vol_i = pi*dp.rad_bar*dp.rad_bar*dp.len_bar+2.0*pi/3.0*((dp.rad_bell-hDist)*(dp.rad_bell-hDist)* 
     336                                                                                (2*dp.rad_bell+hDist)); 
    279337                                                double _ptvalue = weights_rad_bar[i].weight 
    280338                                                                                        * weights_len_bar[j].weight 
     
    283341                                                                                        * weights_phi[m].weight 
    284342                                                                                        * vol_i 
    285                                                                                         * output; 
     343                                                                                        * barbell_analytical_2DXY(&dp, qx, qy); 
     344                                                                                        //* output; 
    286345                                                                                        //* pow(weights_rad[i].value,3.0); 
    287346 
Note: See TracChangeset for help on using the changeset viewer.