Changeset 3044216 in sasmodels
- Timestamp:
- Mar 20, 2016 9:45:51 AM (9 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:
- 0cbcec4
- Parents:
- 44f39a2
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/kernel_iq.c
r44f39a2 r3044216 54 54 var.sld, \ 55 55 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) 56 66 57 67 Our design supports a limited number of polydispersity loops, wherein … … 125 135 operation is not in the inner loop, a slower algorithm can be used. 126 136 137 If there is no polydispersity we pretend that it is polydisperisty with one 138 parameter. 139 127 140 The problem details structure can be allocated and sent in as an integer 128 141 array using the read-only flag. This allows us to copy it once per fit … … 147 160 that the results array be allocated read-write, which is less efficient 148 161 for the GPU, but it makes the calling sequence much more manageable. 162 163 TODO: cutoff 149 164 */ 150 165 … … 176 191 global const double *q, // nq q values, with padding to boundary 177 192 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 180 194 const double cutoff, // cutoff in the polydispersity weight product 181 195 const int pd_start, // where we are in the polydispersity loop … … 183 197 ) 184 198 { 199 185 200 // Storage for the current parameter values. These will be updated as we 186 201 // walk the polydispersity cube. … … 188 203 const double *parvec = &local_pars; // Alias named parameters with a vector 189 204 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 190 225 // Since we are no longer looping over the entire polydispersity hypercube 191 226 // for each q, we need to track the normalization values for each q in a 192 227 // separate work vector. 193 double *norm = work; // contains sum over weights194 double *vol = norm + (nq + padding); // contains sum over volume195 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 196 231 197 232 // Initialize the results to zero 198 233 if (pd_start == 0) { 234 norm_vol = 0.0; 235 norm = 0.0; 236 vol = 0.0; 237 199 238 #ifdef USE_OPENMP 200 239 #pragma omp parallel for 201 240 #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++) { 206 242 result[i] = 0.0; 207 243 } 244 } else { 245 //Pulling values from previous segment 246 norm = result[nq]; 247 vol = result[nq+1]; 248 norm_vol = results[nq+2]; 208 249 } 209 250 210 // Location in the polydispersity cube, one index per dimension.251 // Location in the polydispersity hypercube, one index per dimension. 211 252 local int pd_index[PD_MAX]; 212 253 … … 215 256 pd_index[0] = pd_length[0]; 216 257 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 217 262 // Loop over the weights then loop over q, accumulating values 218 // par219 double partial_weight = NaN;220 263 for (int loop_index=pd_start; loop_index < pd_stop; loop_index++) { 221 264 // check if indices need to be updated … … 223 266 pd_index[0] = loop_index%pd_length[0]; 224 267 partial_weight = 1.0; 225 for (int k= 0; k < MAX_PD; k++) {268 for (int k=1; k < MAX_PD; k++) { 226 269 pd_index[k] = (loop_index%pd_length[k])/pd_stride[k]; 227 270 partial_weight *= weights[pd_offset[k]+pd_index[k]]; … … 230 273 for (int k=0; k < NPARS; k++) { 231 274 int coord = par_coord[k]; 232 int this_offset = 0;275 int this_offset = par_offset[k]; 233 276 int block_size = 1; 234 277 for (int bit=0; bit < MAX_PD && coord != 0; bit++) { … … 240 283 } 241 284 offset[k] = this_offset; 285 parvec[k] = pars[this_offset]; 242 286 } 243 287 } else { … … 249 293 } 250 294 } 295 #ifdef INVALID 296 if (INVALID(local_pars)) continue; 297 #endif 251 298 if (weight > cutoff) { 252 299 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 254 305 #ifdef USE_OPENMP 255 306 #pragma omp parallel for 256 307 #endif 257 for (int i=0; i < Nq; i++) {308 for (int i=0; i < nq; i++) { 258 309 { 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 } 270 314 } 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 272 321 if (pd_stop == pd_stride[MAX_PD-1]) {} 273 322 #ifdef USE_OPENMP 274 323 #pragma omp parallel for 275 324 #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; 281 330 } 282 331 }
Note: See TracChangeset
for help on using the changeset viewer.