Changeset a738209 in sasmodels for sasmodels/kernel_iq.c
- Timestamp:
- Jul 15, 2016 9:33:33 AM (8 years ago)
- 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
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/kernel_iq.c
rae2b6b5 ra738209 22 22 int32_t pd_stride[MAX_PD]; // stride to move to the next index at this level 23 23 #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 27 26 int32_t num_active; // number of non-trivial pd loops 28 int32_t total_pd; // total number of voxels in hypercube29 int32_t num_coord; // number of coordinated parameters30 27 int32_t theta_par; // id of spherical correction variable 31 28 } ProblemDetails; … … 43 40 const int32_t pd_stop, // where we are stopping in the polydispersity loop 44 41 global const ProblemDetails *details, 45 global const double *weights,46 42 global const double *values, 47 43 global const double *q, // nq q values, with padding to boundary … … 54 50 ParameterBlock local_values; // current parameter values 55 51 double *pvec = (double *)(&local_values); // Alias named parameters with a vector 56 double norm;57 58 // number of active loops59 const int num_active = details->num_active;60 52 61 53 // Fill in the initial variables … … 64 56 #endif 65 57 for (int k=0; k < NPARS; k++) { 66 pvec[k] = values[ details->par_offset[k]];58 pvec[k] = values[k+2]; 67 59 } 68 60 69 61 // Monodisperse computation 70 if (num_active == 0) { 62 if (details->num_active == 0) { 63 double norm, scale, background; 71 64 #ifdef INVALID 72 65 if (INVALID(local_values)) { return; } 73 66 #endif 67 74 68 norm = CALL_VOLUME(local_values); 75 76 double scale, background;77 69 scale = values[0]; 78 70 background = values[1]; … … 90 82 #if MAX_PD > 0 91 83 84 const double *pd_value = values+2+NPARS; 85 const double *pd_weight = pd_value+details->pd_sum; 86 92 87 // need product of weights at every Iq calc, so keep product of 93 88 // weights from the outer loops so that weight = partial_weight * fast_weight 89 double pd_norm; 94 90 double partial_weight; // product of weight w4*w3*w2 but not w1 95 91 double spherical_correction; // cosine correction for latitude variation 96 92 double weight; // product of partial_weight*w1*spherical_correction 97 93 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 indices105 const int num_coord = details->num_coord;106 107 94 // 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; 109 100 110 101 // Trigger the reset behaviour that happens at the end the fast loop 111 102 // by setting the initial index >= weight vector length. 112 p d_index[0] = fast_length;103 p0_index = p0_length; 113 104 114 105 // Default the spherical correction to 1.0 in case it is not otherwise set … … 119 110 // calls. This means initializing them to 0 at the start and accumulating 120 111 // them between calls. 121 norm = pd_start == 0 ? 0.0 : result[nq]; 112 pd_norm = (pd_start == 0 ? 0.0 : result[nq]); 113 122 114 if (pd_start == 0) { 123 115 #ifdef USE_OPENMP … … 132 124 for (int loop_index=pd_start; loop_index < pd_stop; loop_index++) { 133 125 // 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) { 136 127 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 144 129 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); 173 137 } 174 138 } 175 //printf("\n");139 p0_index = loop_index%p0_length; 176 140 } 177 141 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); 190 147 } 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++; 197 149 198 150 #ifdef INVALID … … 206 158 // where it becomes zero. If the entirety of the correction 207 159 weight *= spherical_correction; 208 norm += weight * CALL_VOLUME(local_values);160 pd_norm += weight * CALL_VOLUME(local_values); 209 161 210 162 #ifdef USE_OPENMP … … 218 170 } 219 171 220 if (pd_stop >= details-> total_pd) {172 if (pd_stop >= details->pd_prod) { 221 173 // End of the PD loop we can normalize 222 174 double scale, background; … … 227 179 #endif 228 180 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); 230 182 } 231 183 } 232 184 233 185 // Remember the updated norm. 234 result[nq] = norm;186 result[nq] = pd_norm; 235 187 #endif // MAX_PD > 0 236 188 }
Note: See TracChangeset
for help on using the changeset viewer.