Changeset a738209 in sasmodels for sasmodels/kernel_iq.c


Ignore:
Timestamp:
Jul 15, 2016 9:33:33 AM (8 years ago)
Author:
Paul Kienzle <pkienzle@…>
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:
def2c1b
Parents:
98ba1fc
Message:

simplify kernels by remove coordination parameter logic

File:
1 edited

Legend:

Unmodified
Added
Removed
  • sasmodels/kernel_iq.c

    rae2b6b5 ra738209  
    2222    int32_t pd_stride[MAX_PD];  // stride to move to the next index at this level 
    2323#endif // MAX_PD > 0 
    24     int32_t par_offset[NPARS];  // offset of par value blocks in the value & weight vector 
    25     int32_t par_coord[NPARS];   // ids of the coordination parameters 
    26     int32_t pd_coord[NPARS];    // polydispersity coordination bitvector 
     24    int32_t pd_prod;            // total number of voxels in hypercube 
     25    int32_t pd_sum;             // total length of the weights vector 
    2726    int32_t num_active;         // number of non-trivial pd loops 
    28     int32_t total_pd;           // total number of voxels in hypercube 
    29     int32_t num_coord;          // number of coordinated parameters 
    3027    int32_t theta_par;          // id of spherical correction variable 
    3128} ProblemDetails; 
     
    4340    const int32_t pd_stop,      // where we are stopping in the polydispersity loop 
    4441    global const ProblemDetails *details, 
    45     global const double *weights, 
    4642    global const double *values, 
    4743    global const double *q, // nq q values, with padding to boundary 
     
    5450  ParameterBlock local_values;  // current parameter values 
    5551  double *pvec = (double *)(&local_values);  // Alias named parameters with a vector 
    56   double norm; 
    57  
    58   // number of active loops 
    59   const int num_active = details->num_active; 
    6052 
    6153  // Fill in the initial variables 
     
    6456  #endif 
    6557  for (int k=0; k < NPARS; k++) { 
    66     pvec[k] = values[details->par_offset[k]]; 
     58    pvec[k] = values[k+2]; 
    6759  } 
    6860 
    6961  // Monodisperse computation 
    70   if (num_active == 0) { 
     62  if (details->num_active == 0) { 
     63    double norm, scale, background; 
    7164    #ifdef INVALID 
    7265    if (INVALID(local_values)) { return; } 
    7366    #endif 
     67 
    7468    norm = CALL_VOLUME(local_values); 
    75  
    76     double scale, background; 
    7769    scale = values[0]; 
    7870    background = values[1]; 
     
    9082#if MAX_PD > 0 
    9183 
     84  const double *pd_value = values+2+NPARS; 
     85  const double *pd_weight = pd_value+details->pd_sum; 
     86 
    9287  // need product of weights at every Iq calc, so keep product of 
    9388  // weights from the outer loops so that weight = partial_weight * fast_weight 
     89  double pd_norm; 
    9490  double partial_weight; // product of weight w4*w3*w2 but not w1 
    9591  double spherical_correction; // cosine correction for latitude variation 
    9692  double weight; // product of partial_weight*w1*spherical_correction 
    9793 
    98   // Location in the polydispersity hypercube, one index per dimension. 
    99   int pd_index[MAX_PD]; 
    100  
    101   // Location of the coordinated parameters in their own sub-cubes. 
    102   int offset[NPARS]; 
    103  
    104   // Number of coordinated indices 
    105   const int num_coord = details->num_coord; 
    106  
    10794  // Number of elements in the longest polydispersity loop 
    108   const int fast_length = details->pd_length[0]; 
     95  const int p0_par = details->pd_par[0]; 
     96  const int p0_length = details->pd_length[0]; 
     97  const int p0_offset = details->pd_offset[0]; 
     98  const int p0_is_theta = (p0_par == details->theta_par); 
     99  int p0_index; 
    109100 
    110101  // Trigger the reset behaviour that happens at the end the fast loop 
    111102  // by setting the initial index >= weight vector length. 
    112   pd_index[0] = fast_length; 
     103  p0_index = p0_length; 
    113104 
    114105  // Default the spherical correction to 1.0 in case it is not otherwise set 
     
    119110  // calls.  This means initializing them to 0 at the start and accumulating 
    120111  // them between calls. 
    121   norm = pd_start == 0 ? 0.0 : result[nq]; 
     112  pd_norm = (pd_start == 0 ? 0.0 : result[nq]); 
     113 
    122114  if (pd_start == 0) { 
    123115    #ifdef USE_OPENMP 
     
    132124  for (int loop_index=pd_start; loop_index < pd_stop; loop_index++) { 
    133125    // check if fast loop needs to be reset 
    134     if (pd_index[0] == fast_length) { 
    135       //printf("should be here with %d active\n", num_active); 
     126    if (p0_index == p0_length) { 
    136127 
    137       // Compute position in polydispersity hypercube 
    138       for (int k=0; k < num_active; k++) { 
    139         pd_index[k] = (loop_index/details->pd_stride[k])%details->pd_length[k]; 
    140         //printf("pd_index[%d] = %d\n",k,pd_index[k]); 
    141       } 
    142  
    143       // Compute partial weights 
     128      // Compute position in polydispersity hypercube and partial weight 
    144129      partial_weight = 1.0; 
    145       //printf("partial weight %d: ", loop_index); 
    146       for (int k=1; k < num_active; k++) { 
    147         double wi = weights[details->pd_offset[k] + pd_index[k]]; 
    148         //printf("pd[%d]=par[%d]=%g ", k, details->pd_par[k], wi); 
    149         partial_weight *= wi; 
    150       } 
    151       //printf("\n"); 
    152  
    153       // Update parameter offsets in weight vector 
    154       //printf("slow %d: ", loop_index); 
    155       for (int k=0; k < num_coord; k++) { 
    156         int par = details->par_coord[k]; 
    157         int coord = details->pd_coord[k]; 
    158         int this_offset = details->par_offset[par]; 
    159         int block_size = 1; 
    160         for (int bit=0; coord != 0; bit++) { 
    161           if (coord&1) { 
    162               this_offset += block_size * pd_index[bit]; 
    163               block_size *= details->pd_length[bit]; 
    164           } 
    165           coord >>= 1; 
    166         } 
    167         offset[par] = this_offset; 
    168         pvec[par] = values[this_offset]; 
    169         //printf("par[%d]=v[%d]=%g \n", k, offset[k], pvec[k]); 
    170         // if theta is not coordinated with fast index, precompute spherical correction 
    171         if (par == details->theta_par && !(details->par_coord[k]&1)) { 
    172           spherical_correction = fmax(fabs(cos(M_PI_180*pvec[details->theta_par])), 1.e-6); 
     130      for (int k=1; k < details->num_active; k++) { 
     131        int pk = details->pd_par[k]; 
     132        int index = details->pd_offset[k] + (loop_index/details->pd_stride[k])%details->pd_length[k]; 
     133        pvec[pk] = pd_value[index]; 
     134        partial_weight *= pd_weight[index]; 
     135        if (pk == details->theta_par) { 
     136          spherical_correction = fmax(fabs(cos(M_PI_180*pvec[pk])), 1.e-6); 
    173137        } 
    174138      } 
    175       //printf("\n"); 
     139      p0_index = loop_index%p0_length; 
    176140    } 
    177141 
    178     // Update fast parameters 
    179     //printf("fast %d: ", loop_index); 
    180     for (int k=0; k < num_coord; k++) { 
    181       if (details->pd_coord[k]&1) { 
    182         const int par = details->par_coord[k]; 
    183         pvec[par] = values[offset[par]++]; 
    184         //printf("p[%d]=v[%d]=%g ", par, offset[par]-1, pvec[par]); 
    185         // if theta is coordinated with fast index, compute spherical correction each time 
    186         if (par == details->theta_par) { 
    187           spherical_correction = fmax(fabs(cos(M_PI_180*pvec[details->theta_par])), 1.e-6); 
    188         } 
    189       } 
     142    // Update parameter p0 
     143    weight = partial_weight*pd_weight[p0_offset + p0_index]; 
     144    pvec[p0_par] = pd_value[p0_offset + p0_index]; 
     145    if (p0_is_theta) { 
     146      spherical_correction = fmax(fabs(cos(M_PI_180*pvec[p0_par])), 1.e-6); 
    190147    } 
    191     //printf("\n"); 
    192  
    193     // Increment fast index 
    194     const double wi = weights[details->pd_offset[0] + pd_index[0]]; 
    195     weight = partial_weight*wi; 
    196     pd_index[0]++; 
     148    p0_index++; 
    197149 
    198150    #ifdef INVALID 
     
    206158      // where it becomes zero.  If the entirety of the correction 
    207159      weight *= spherical_correction; 
    208       norm += weight * CALL_VOLUME(local_values); 
     160      pd_norm += weight * CALL_VOLUME(local_values); 
    209161 
    210162      #ifdef USE_OPENMP 
     
    218170  } 
    219171 
    220   if (pd_stop >= details->total_pd) { 
     172  if (pd_stop >= details->pd_prod) { 
    221173    // End of the PD loop we can normalize 
    222174    double scale, background; 
     
    227179    #endif 
    228180    for (int q_index=0; q_index < nq; q_index++) { 
    229       result[q_index] = (norm>0. ? scale*result[q_index]/norm + background : background); 
     181      result[q_index] = (pd_norm>0. ? scale*result[q_index]/pd_norm + background : background); 
    230182    } 
    231183  } 
    232184 
    233185  // Remember the updated norm. 
    234   result[nq] = norm; 
     186  result[nq] = pd_norm; 
    235187#endif // MAX_PD > 0 
    236188} 
Note: See TracChangeset for help on using the changeset viewer.