Changeset 3044216 in sasmodels for sasmodels/kernel_iq.c


Ignore:
Timestamp:
Mar 20, 2016 9:45:51 AM (8 years ago)
Author:
wojciech
Branches:
master, core_shell_microgels, costrafo411, magnetic_model, release_v0.94, release_v0.95, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
Children:
0cbcec4
Parents:
44f39a2
Message:

Polydispersity loop proototype

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sasmodels/kernel_iq.c

    r44f39a2 r3044216  
    5454           var.sld, \ 
    5555           var.sld_solvent 
     56 
     57   INVALID is a test for model parameters in the correct range 
     58 
     59       Cylinder: 
     60 
     61           #define INVALID(var) 0 
     62 
     63       BarBell: 
     64 
     65           #define INVALID(var) (var.bell_radius > var.radius) 
    5666 
    5767Our design supports a limited number of polydispersity loops, wherein 
     
    125135operation is not in the inner loop, a slower algorithm can be used. 
    126136 
     137If there is no polydispersity we pretend that it is polydisperisty with one 
     138parameter. 
     139 
    127140The problem details structure can be allocated and sent in as an integer 
    128141array using the read-only flag.  This allows us to copy it once per fit 
     
    147160that the results array be allocated read-write, which is less efficient 
    148161for the GPU, but it makes the calling sequence much more manageable. 
     162 
     163TODO: cutoff 
    149164*/ 
    150165 
     
    176191    global const double *q, // nq q values, with padding to boundary 
    177192    global double *result,  // nq return values, again with padding 
    178     global double *work,    // 3*(nq+padding) space for normalization 
    179     global int *int_work,   // nq+padding space for current position 
     193    global int *offset,     // nq+padding space for current parameter index 
    180194    const double cutoff,    // cutoff in the polydispersity weight product 
    181195    const int pd_start,     // where we are in the polydispersity loop 
     
    183197    ) 
    184198{ 
     199 
    185200  // Storage for the current parameter values.  These will be updated as we 
    186201  // walk the polydispersity cube. 
     
    188203  const double *parvec = &local_pars;  // Alias named parameters with a vector 
    189204 
     205#if defined(USE_SHORTCUT_OPTIMIZATION) 
     206  if (pd_length[0] == 1) { 
     207    // Shouldn't need to copy!! 
     208    for (int k=0; k < NPARS; k++) { 
     209      parvec[k] = pars[k]; 
     210    } 
     211 
     212    #ifdef USE_OPENMP 
     213    #pragma omp parallel for 
     214    #endif 
     215    for (int i=0; i < nq; i++) { 
     216    { 
     217      const double scattering = IQ_FUNC(IQ_PARS, IQ_PARAMETERS); 
     218      result[i] += local_pars.scale*scattering + local_pars.background; 
     219    } 
     220    return; 
     221  } 
     222#endif 
     223 
     224 
    190225  // Since we are no longer looping over the entire polydispersity hypercube 
    191226  // for each q, we need to track the normalization values for each q in a 
    192227  // separate work vector. 
    193   double *norm = work;   // contains sum over weights 
    194   double *vol = norm + (nq + padding); // contains sum over volume 
    195   double *norm_vol = vol + (nq + padding); 
     228  double norm;   // contains sum over weights 
     229  double vol; // contains sum over volume 
     230  double norm_vol; // contains weights over volume 
    196231 
    197232  // Initialize the results to zero 
    198233  if (pd_start == 0) { 
     234    norm_vol = 0.0; 
     235    norm = 0.0; 
     236    vol = 0.0; 
     237 
    199238    #ifdef USE_OPENMP 
    200239    #pragma omp parallel for 
    201240    #endif 
    202     for (int i=0; i < Nq; i++) { 
    203       norm_vol[i] = 0.0; 
    204       norm[i] = 0.0; 
    205       vol[i] = 0.0; 
     241    for (int i=0; i < nq; i++) { 
    206242      result[i] = 0.0; 
    207243    } 
     244  } else { 
     245    //Pulling values from previous segment 
     246    norm = result[nq]; 
     247    vol = result[nq+1]; 
     248    norm_vol = results[nq+2]; 
    208249  } 
    209250 
    210   // Location in the polydispersity cube, one index per dimension. 
     251  // Location in the polydispersity hypercube, one index per dimension. 
    211252  local int pd_index[PD_MAX]; 
    212253 
     
    215256  pd_index[0] = pd_length[0]; 
    216257 
     258  // need product of weights at every Iq calc, so keep product of 
     259  // weights from the outer loops so that weight = partial_weight * fast_weight 
     260  double partial_weight = NAN; // product of weight w4*w3*w2 but not w1 
     261 
    217262  // Loop over the weights then loop over q, accumulating values 
    218   // par 
    219   double partial_weight = NaN; 
    220263  for (int loop_index=pd_start; loop_index < pd_stop; loop_index++) { 
    221264    // check if indices need to be updated 
     
    223266      pd_index[0] = loop_index%pd_length[0]; 
    224267      partial_weight = 1.0; 
    225       for (int k=0; k < MAX_PD; k++) { 
     268      for (int k=1; k < MAX_PD; k++) { 
    226269        pd_index[k] = (loop_index%pd_length[k])/pd_stride[k]; 
    227270        partial_weight *= weights[pd_offset[k]+pd_index[k]]; 
     
    230273      for (int k=0; k < NPARS; k++) { 
    231274        int coord = par_coord[k]; 
    232         int this_offset = 0; 
     275        int this_offset = par_offset[k]; 
    233276        int block_size = 1; 
    234277        for (int bit=0; bit < MAX_PD && coord != 0; bit++) { 
     
    240283        } 
    241284        offset[k] = this_offset; 
     285        parvec[k] = pars[this_offset]; 
    242286      } 
    243287    } else { 
     
    249293      } 
    250294    } 
     295    #ifdef INVALID 
     296    if (INVALID(local_pars)) continue; 
     297    #endif 
    251298    if (weight > cutoff) { 
    252299      const double vol_weight = VOLUME_WEIGHT_PRODUCT; 
    253       const double weighted_vol = vol_weight*form_volume(VOLUME_PARAMTERS); 
     300      const double weighted_vol = vol_weight*form_volume(VOLUME_PARAMETERS); 
     301      norm += weight; 
     302      vol += weighted_vol; 
     303      norm_vol += vol_weight; 
     304 
    254305      #ifdef USE_OPENMP 
    255306      #pragma omp parallel for 
    256307      #endif 
    257       for (int i=0; i < Nq; i++) { 
     308      for (int i=0; i < nq; i++) { 
    258309      { 
    259         const double scattering = Iq(qi, IQ_PARAMETERS); 
    260         // allow kernels to exclude invalid regions by returning NaN 
    261         if (!isnan(scattering)) { 
    262           result[i] += weight*scattering; 
    263           // can almost get away with only having one constant rather than 
    264           // one constant per q.  Maybe want a "is_valid" test? 
    265           norm[i] += weight; 
    266           vol[i] += weighted_vol; 
    267           norm_vol[i] += vol_weight; 
    268         } 
    269     } 
     310        const double scattering = IQ_FUNC(IQ_PARS, IQ_PARAMETERS); 
     311        //const double scattering = Iq(q[i], IQ_PARAMETERS); 
     312        result[i] += weight*scattering; 
     313      } 
    270314  } 
    271  
     315  //Makes a normalization avialable for the next round 
     316  result[nq] = norm; 
     317  result[nq+1] = vol; 
     318  results[nq+2] = norm_vol; 
     319 
     320  //End of the PD loop we can normalize 
    272321  if (pd_stop == pd_stride[MAX_PD-1]) {} 
    273322    #ifdef USE_OPENMP 
    274323    #pragma omp parallel for 
    275324    #endif 
    276     for (int i=0; i < Nq; i++) { 
    277       if (vol[i]*norm_vol[i] != 0.0) { 
    278         result[i] *= norm_vol[i]/vol[i]; 
    279       } 
    280         result[i] = scale*result[i]/norm[i]+background; 
     325    for (int i=0; i < nq; i++) { 
     326      if (vol*norm_vol != 0.0) { 
     327        result[i] *= norm_vol/vol; 
     328      } 
     329        result[i] = local_pars.scale*result[i]/norm+local_pars.background; 
    281330    } 
    282331  } 
Note: See TracChangeset for help on using the changeset viewer.