Changes in / [6b7e2f7:524e5c4] in sasmodels
- Location:
- sasmodels
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/core.py
r725ee36 r3d9001f 33 33 except ImportError: 34 34 pass 35 36 try: 37 np.meshgrid([]) 38 meshgrid = np.meshgrid 39 except Exception: 40 # CRUFT: np.meshgrid requires multiple vectors 41 def meshgrid(*args): 42 """Allow meshgrid with a single argument""" 43 if len(args) > 1: 44 return np.meshgrid(*args) 45 else: 46 return [np.asarray(v) for v in args] 35 47 36 48 # TODO: refactor composite model support -
sasmodels/details.py
r725ee36 r40a87fa 20 20 np.meshgrid([]) 21 21 meshgrid = np.meshgrid 22 except Exception:22 except ValueError: 23 23 # CRUFT: np.meshgrid requires multiple vectors 24 24 def meshgrid(*args): … … 71 71 # pd_offset[max_pd] offset of pd values in parameter array 72 72 # pd_stride[max_pd] index of pd value in loop = n//stride[k] 73 # num_evaltotal length of pd loop74 # num_weightstotal length of the weight vector73 # pd_prod total length of pd loop 74 # pd_sum total length of the weight vector 75 75 # num_active number of pd params 76 76 # theta_par parameter number for theta parameter 77 self.buffer = np. empty(4*max_pd + 4, 'i4')77 self.buffer = np.zeros(4*max_pd + 4, 'i4') 78 78 79 79 # generate views on different parts of the array … … 86 86 self.theta_par = parameters.theta_offset 87 87 88 # offset and length are for all parameters, not just pd parameters89 # They are not sent to the kernel function, though they could be.90 # They are used by the composite models (sum and product) to91 # figure out offsets into the combined value list.92 self.offset = None # type: np.ndarray93 self.length = None # type: np.ndarray94 95 # keep hold of ifno show() so we can break a values vector96 # into the individual components97 self.info = model_info98 99 88 @property 100 89 def pd_par(self): … … 118 107 119 108 @property 120 def num_eval(self):109 def pd_prod(self): 121 110 """Total size of the pd mesh""" 122 111 return self.buffer[-4] 123 112 124 @ num_eval.setter125 def num_eval(self, v):113 @pd_prod.setter 114 def pd_prod(self, v): 126 115 """Total size of the pd mesh""" 127 116 self.buffer[-4] = v 128 117 129 118 @property 130 def num_weights(self):119 def pd_sum(self): 131 120 """Total length of all the weight vectors""" 132 121 return self.buffer[-3] 133 122 134 @ num_weights.setter135 def num_weights(self, v):123 @pd_sum.setter 124 def pd_sum(self, v): 136 125 """Total length of all the weight vectors""" 137 126 self.buffer[-3] = v … … 157 146 self.buffer[-1] = v 158 147 159 def show(self , values=None):148 def show(self): 160 149 """Print the polydispersity call details to the console""" 161 print("===== %s details ===="%self.info.name) 162 print("num_active:%d num_eval:%d num_weights:%d theta=%d" 163 % (self.num_active, self.num_eval, self.num_weights, self.theta_par)) 164 if self.pd_par.size: 165 print("pd_par", self.pd_par) 166 print("pd_length", self.pd_length) 167 print("pd_offset", self.pd_offset) 168 print("pd_stride", self.pd_stride) 169 if values is not None: 170 nvalues = self.info.parameters.nvalues 171 print("scale, background", values[:2]) 172 print("val", values[2:nvalues]) 173 print("pd", values[nvalues:nvalues+self.num_weights]) 174 print("wt", values[nvalues+self.num_weights:nvalues+2*self.num_weights]) 175 print("offsets", self.offset) 176 177 178 def make_details(model_info, length, offset, num_weights): 150 print("num_active", self.num_active) 151 print("pd_prod", self.pd_prod) 152 print("pd_sum", self.pd_sum) 153 print("theta par", self.theta_par) 154 print("pd_par", self.pd_par) 155 print("pd_length", self.pd_length) 156 print("pd_offset", self.pd_offset) 157 print("pd_stride", self.pd_stride) 158 159 160 def mono_details(model_info): 161 # type: (ModelInfo) -> CallDetails 162 """ 163 Return a :class:`CallDetails` object for a monodisperse calculation 164 of the model defined by *model_info*. 165 """ 166 call_details = CallDetails(model_info) 167 call_details.pd_prod = 1 168 call_details.pd_sum = model_info.parameters.nvalues 169 call_details.pd_par[:] = np.arange(0, model_info.parameters.max_pd) 170 call_details.pd_length[:] = 1 171 call_details.pd_offset[:] = np.arange(0, model_info.parameters.max_pd) 172 call_details.pd_stride[:] = 1 173 return call_details 174 175 176 def poly_details(model_info, weights): 179 177 """ 180 178 Return a :class:`CallDetails` object for a polydisperse calculation 181 of the model defined by *model_info*. Polydispersity is defined by 182 the *length* of the polydispersity distribution for each parameter 183 and the *offset* of the distribution in the polydispersity array. 184 Monodisperse parameters should use a polydispersity length of one 185 with weight 1.0. *num_weights* is the total length of the polydispersity 186 array. 187 """ 188 # type: (ModelInfo, np.ndarray, np.ndarray, int) -> CallDetails 189 #pars = model_info.parameters.call_parameters[2:model_info.parameters.npars+2] 190 #print(", ".join(str(i)+"-"+p.id for i,p in enumerate(pars))) 191 #print("len:",length) 192 #print("off:",offset) 193 194 # Check that we arn't using too many polydispersity loops 195 num_active = np.sum(length > 1) 179 of the model defined by *model_info* for the given set of *weights*. 180 *weights* is a list of vectors, one for each parameter. Monodisperse 181 parameters should provide a weight vector containing [1.0]. 182 """ 183 # type: (ModelInfo) -> CallDetails 184 #print("weights",weights) 185 #weights = weights[2:] # Skip scale and background 186 187 # Decreasing list of polydispersity lengths 188 #print([p.id for p in model_info.parameters.call_parameters]) 189 pd_length = np.array([len(w) 190 for w in weights[2:2+model_info.parameters.npars]]) 191 num_active = np.sum(pd_length > 1) 196 192 max_pd = model_info.parameters.max_pd 197 193 if num_active > max_pd: 198 194 raise ValueError("Too many polydisperse parameters") 199 195 200 # Decreasing list of polydpersity lengths 196 pd_offset = np.cumsum(np.hstack((0, pd_length))) 197 #print(", ".join(str(i)+"-"+p.id for i,p in enumerate(model_info.parameters.call_parameters))) 198 #print("len:",pd_length) 199 #print("off:",pd_offset) 201 200 # Note: the reversing view, x[::-1], does not require a copy 202 idx = np.argsort( length)[::-1][:max_pd]203 pd_stride = np.cumprod(np.hstack((1, length[idx])))201 idx = np.argsort(pd_length)[::-1][:max_pd] 202 pd_stride = np.cumprod(np.hstack((1, pd_length[idx]))) 204 203 205 204 call_details = CallDetails(model_info) 206 205 call_details.pd_par[:max_pd] = idx 207 call_details.pd_length[:max_pd] = length[idx]208 call_details.pd_offset[:max_pd] = offset[idx]206 call_details.pd_length[:max_pd] = pd_length[idx] 207 call_details.pd_offset[:max_pd] = pd_offset[idx] 209 208 call_details.pd_stride[:max_pd] = pd_stride[:-1] 210 call_details. num_eval= pd_stride[-1]211 call_details. num_weights = num_weights209 call_details.pd_prod = pd_stride[-1] 210 call_details.pd_sum = sum(len(w) for w in weights) 212 211 call_details.num_active = num_active 213 call_details.length = length214 call_details.offset = offset215 212 #call_details.show() 216 213 return call_details 217 218 219 ZEROS = tuple([0.]*31)220 def make_kernel_args(kernel, pairs):221 # type: (Kernel, Tuple[List[np.ndarray], List[np.ndarray]]) -> Tuple[CallDetails, np.ndarray, bool]222 """223 Converts (value, weight) pairs into parameters for the kernel call.224 225 Returns a CallDetails object indicating the polydispersity, a data object226 containing the different values, and the magnetic flag indicating whether227 any magnetic magnitudes are non-zero. Magnetic vectors (M0, phi, theta) are228 converted to rectangular coordinates (mx, my, mz).229 """230 npars = kernel.info.parameters.npars231 nvalues = kernel.info.parameters.nvalues232 scalars = [v[0][0] for v in pairs]233 values, weights = zip(*pairs[2:npars+2]) if npars else ((),())234 length = np.array([len(w) for w in weights])235 offset = np.cumsum(np.hstack((0, length)))236 call_details = make_details(kernel.info, length, offset[:-1], offset[-1])237 # Pad value array to a 32 value boundaryd238 data_len = nvalues + 2*sum(len(v) for v in values)239 extra = (32 - data_len%32)%32240 data = np.hstack((scalars,) + values + weights + ZEROS[:extra])241 data = data.astype(kernel.dtype)242 is_magnetic = convert_magnetism(kernel.info.parameters, data)243 #call_details.show()244 return call_details, data, is_magnetic245 246 247 def convert_magnetism(parameters, values):248 """249 Convert magnetism values from polar to rectangular coordinates.250 251 Returns True if any magnetism is present.252 """253 mag = values[parameters.nvalues-3*parameters.nmagnetic:parameters.nvalues]254 mag = mag.reshape(-1, 3)255 scale = mag[:,0]256 if np.any(scale):257 theta, phi = mag[:, 1]*pi/180., mag[:, 2]*pi/180.258 cos_theta = cos(theta)259 mag[:, 0] = scale*cos_theta*cos(phi) # mx260 mag[:, 1] = scale*sin(theta) # my261 mag[:, 2] = -scale*cos_theta*sin(phi) # mz262 return True263 else:264 return False265 214 266 215 … … 290 239 value = pars 291 240 return value, weight 241 242 243 244 def build_details(kernel, pairs): 245 # type: (Kernel, Tuple[List[np.ndarray], List[np.ndarray]]) -> Tuple[CallDetails, np.ndarray, bool] 246 """ 247 Converts (value, weight) pairs into parameters for the kernel call. 248 249 Returns a CallDetails object indicating the polydispersity, a data object 250 containing the different values, and the magnetic flag indicating whether 251 any magnetic magnitudes are non-zero. Magnetic vectors (M0, phi, theta) are 252 converted to rectangular coordinates (mx, my, mz). 253 """ 254 values, weights = zip(*pairs) 255 scalars = [v[0] for v in values] 256 if all(len(w) == 1 for w in weights): 257 call_details = mono_details(kernel.info) 258 # Pad value array to a 32 value boundary 259 data_len = 3*len(scalars) 260 extra = ((data_len+31)//32)*32 - data_len 261 data = np.array(scalars+scalars+[1.]*len(scalars)+[0.]*extra, 262 dtype=kernel.dtype) 263 else: 264 call_details = poly_details(kernel.info, weights) 265 # Pad value array to a 32 value boundary 266 data_len = len(scalars) + 2*sum(len(v) for v in values) 267 extra = ((data_len+31)//32)*32 - data_len 268 data = np.hstack(scalars+list(values)+list(weights)+[0.]*extra) 269 data = data.astype(kernel.dtype) 270 is_magnetic = convert_magnetism(kernel.info.parameters, data) 271 #call_details.show() 272 return call_details, data, is_magnetic 273 274 def convert_magnetism(parameters, values): 275 """ 276 Convert magnetism values from polar to rectangular coordinates. 277 278 Returns True if any magnetism is present. 279 """ 280 mag = values[parameters.nvalues-3*parameters.nmagnetic:parameters.nvalues] 281 mag = mag.reshape(-1, 3) 282 scale = mag[:,0] 283 if np.any(scale): 284 theta, phi = mag[:, 1]*pi/180., mag[:, 2]*pi/180. 285 cos_theta = cos(theta) 286 mag[:, 0] = scale*cos_theta*cos(phi) # mx 287 mag[:, 1] = scale*sin(theta) # my 288 mag[:, 2] = -scale*cos_theta*sin(phi) # mz 289 return True 290 else: 291 return False -
sasmodels/direct_model.py
rbde38b5 r40a87fa 30 30 from . import resolution 31 31 from . import resolution2d 32 from .details import make_kernel_args, dispersion_mesh32 from .details import build_details, dispersion_mesh 33 33 34 34 try: … … 70 70 for p in parameters.call_parameters] 71 71 72 call_details, values, is_magnetic = make_kernel_args(calculator, vw_pairs)72 call_details, values, is_magnetic = build_details(calculator, vw_pairs) 73 73 #print("values:", values) 74 74 return calculator(call_details, values, cutoff, is_magnetic) -
sasmodels/kernel.py
rbde38b5 r9eb3632 39 39 info = None # type: ModelInfo 40 40 results = None # type: List[np.ndarray] 41 dtype = None # type: np.dtype42 41 43 42 def __call__(self, call_details, values, cutoff, magnetic): -
sasmodels/kernel_iq.c
rbde38b5 r0f00d95 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 num_eval;// total number of voxels in hypercube25 int32_t num_weights;// total length of the weights vector24 int32_t pd_prod; // total number of voxels in hypercube 25 int32_t pd_sum; // total length of the weights vector 26 26 int32_t num_active; // number of non-trivial pd loops 27 27 int32_t theta_par; // id of spherical correction variable 28 28 } ProblemDetails; 29 29 30 // Intel HD 4000 needs private arrays to be a multiple of 4 long31 30 typedef struct { 32 31 PARAMETER_TABLE 33 } ParameterTable;34 typedef union {35 ParameterTable table;36 double vector[4*((NUM_PARS+3)/4)];37 32 } ParameterBlock; 38 33 #endif // _PAR_BLOCK_ … … 84 79 ) 85 80 { 81 86 82 // Storage for the current parameter values. These will be updated as we 87 // walk the polydispersity cube. 83 // walk the polydispersity cube. local_values will be aliased to pvec. 88 84 ParameterBlock local_values; 85 double *pvec = (double *)&local_values; 89 86 90 87 #if defined(MAGNETIC) && NUM_MAGNETIC>0 91 // Location of the sld parameters in the parameter vector.88 // Location of the sld parameters in the parameter pvec. 92 89 // These parameters are updated with the effective sld due to magnetism. 93 90 #if NUM_MAGNETIC > 3 … … 113 110 #endif 114 111 for (int i=0; i < NUM_PARS; i++) { 115 local_values.vector[i] = values[2+i]; 116 //printf("p%d = %g\n",i, local_values.vector[i]); 117 } 118 //printf("NUM_VALUES:%d NUM_PARS:%d MAX_PD:%d\n", NUM_VALUES, NUM_PARS, MAX_PD); 119 //printf("start:%d stop:%d\n", pd_start, pd_stop); 120 121 double pd_norm = (pd_start == 0 ? 0.0 : result[nq]); 112 pvec[i] = values[2+i]; 113 //printf("p%d = %g\n",i, pvec[i]); 114 } 115 116 double pd_norm; 117 //printf("start: %d %d\n",pd_start, pd_stop); 122 118 if (pd_start == 0) { 119 pd_norm = 0.0; 123 120 #ifdef USE_OPENMP 124 121 #pragma omp parallel for 125 122 #endif 126 123 for (int q_index=0; q_index < nq; q_index++) result[q_index] = 0.0; 124 //printf("initializing %d\n", nq); 125 } else { 126 pd_norm = result[nq]; 127 127 } 128 128 //printf("start %d %g %g\n", pd_start, pd_norm, result[0]); 129 129 130 130 #if MAX_PD>0 131 global const double *pd_value = values + NUM_VALUES ;132 global const double *pd_weight = pd_value + details-> num_weights;131 global const double *pd_value = values + NUM_VALUES + 2; 132 global const double *pd_weight = pd_value + details->pd_sum; 133 133 #endif 134 134 … … 169 169 global const double *v0 = pd_value + details->pd_offset[0]; 170 170 global const double *w0 = pd_weight + details->pd_offset[0]; 171 //printf("w0:%p, values:%p, diff:% ld, %d\n",w0,values,(w0-values),NUM_VALUES);171 //printf("w0:%p, values:%p, diff:%d, %d\n",w0,values,(w0-values),NUM_VALUES); 172 172 #endif 173 173 … … 186 186 int step = pd_start; 187 187 188 188 189 #if MAX_PD>4 189 190 const double weight5 = 1.0; 190 191 while (i4 < n4) { 191 local_values.vector[p4] = v4[i4];192 pvec[p4] = v4[i4]; 192 193 double weight4 = w4[i4] * weight5; 193 //printf("step:%d level %d: p:%d i:%d n:%d value:%g weight:%g\n", step, 4, p4, i4, n4, local_values.vector[p4], weight4);194 //printf("step:%d level %d: p:%d i:%d n:%d value:%g weight:%g\n", step, 4, p4, i4, n4, pvec[p4], weight4); 194 195 #elif MAX_PD>3 195 196 const double weight4 = 1.0; … … 197 198 #if MAX_PD>3 198 199 while (i3 < n3) { 199 local_values.vector[p3] = v3[i3];200 pvec[p3] = v3[i3]; 200 201 double weight3 = w3[i3] * weight4; 201 //printf("step:%d level %d: p:%d i:%d n:%d value:%g weight:%g\n", step, 3, p3, i3, n3, local_values.vector[p3], weight3);202 //printf("step:%d level %d: p:%d i:%d n:%d value:%g weight:%g\n", step, 3, p3, i3, n3, pvec[p3], weight3); 202 203 #elif MAX_PD>2 203 204 const double weight3 = 1.0; … … 205 206 #if MAX_PD>2 206 207 while (i2 < n2) { 207 local_values.vector[p2] = v2[i2];208 pvec[p2] = v2[i2]; 208 209 double weight2 = w2[i2] * weight3; 209 //printf("step:%d level %d: p:%d i:%d n:%d value:%g weight:%g\n", step, 2, p2, i2, n2, local_values.vector[p2], weight2);210 //printf("step:%d level %d: p:%d i:%d n:%d value:%g weight:%g\n", step, 2, p2, i2, n2, pvec[p2], weight2); 210 211 #elif MAX_PD>1 211 212 const double weight2 = 1.0; … … 213 214 #if MAX_PD>1 214 215 while (i1 < n1) { 215 local_values.vector[p1] = v1[i1];216 pvec[p1] = v1[i1]; 216 217 double weight1 = w1[i1] * weight2; 217 //printf("step:%d level %d: p:%d i:%d n:%d value:%g weight:%g\n", step, 1, p1, i1, n1, local_values.vector[p1], weight1);218 //printf("step:%d level %d: p:%d i:%d n:%d value:%g weight:%g\n", step, 1, p1, i1, n1, pvec[p1], weight1); 218 219 #elif MAX_PD>0 219 220 const double weight1 = 1.0; … … 221 222 #if MAX_PD>0 222 223 if (slow_theta) { // Theta is not in inner loop 223 spherical_correction = fmax(fabs(cos(M_PI_180* local_values.vector[theta_par])), 1.e-6);224 spherical_correction = fmax(fabs(cos(M_PI_180*pvec[theta_par])), 1.e-6); 224 225 } 225 226 while(i0 < n0) { 226 local_values.vector[p0] = v0[i0];227 pvec[p0] = v0[i0]; 227 228 double weight0 = w0[i0] * weight1; 228 //printf("step:%d level %d: p:%d i:%d n:%d value:%g weight:%g\n", step, 0, p0, i0, n0, local_values.vector[p0], weight0);229 //printf("step:%d level %d: p:%d i:%d n:%d value:%g weight:%g\n", step, 0, p0, i0, n0, pvec[p0], weight0); 229 230 if (fast_theta) { // Theta is in inner loop 230 spherical_correction = fmax(fabs(cos(M_PI_180* local_values.vector[p0])), 1.e-6);231 spherical_correction = fmax(fabs(cos(M_PI_180*pvec[p0])), 1.e-6); 231 232 } 232 233 #else … … 234 235 #endif 235 236 236 //printf("step:%d of %d, pars:",step,pd_stop); for (int i=0; i < NUM_PARS; i++) printf("p%d=%g ",i, local_values.vector[i]); printf("\n");237 //printf("step:%d of %d, pars:",step,pd_stop); for (int i=0; i < NUM_PARS; i++) printf("p%d=%g ",i, pvec[i]); printf("\n"); 237 238 //printf("sphcor: %g\n", spherical_correction); 238 239 239 240 #ifdef INVALID 240 if (!INVALID(local_values .table))241 if (!INVALID(local_values)) 241 242 #endif 242 243 { … … 247 248 // would be problems looking at models with theta=90. 248 249 const double weight = weight0 * spherical_correction; 249 pd_norm += weight * CALL_VOLUME(local_values .table);250 pd_norm += weight * CALL_VOLUME(local_values); 250 251 251 252 #ifdef USE_OPENMP … … 262 263 // TODO: what is the magnetic scattering at q=0 263 264 if (qsq > 1.e-16) { 264 double p[4]; // dd, du, ud, uu265 double p[4]; 265 266 p[0] = (qy*cos_mspin + qx*sin_mspin)/qsq; 266 267 p[3] = -p[0]; … … 277 278 #define M3 NUM_PARS+13 278 279 #define SLD(_M_offset, _sld_offset) \ 279 local_values.vector[_sld_offset] = xs * (axis \280 pvec[_sld_offset] = xs * (axis \ 280 281 ? (index==1 ? -values[_M_offset+2] : values[_M_offset+2]) \ 281 282 : mag_sld(qx, qy, pk, values[_M_offset], values[_M_offset+1], \ … … 295 296 } 296 297 #endif 297 scattering += CALL_IQ(q, q_index, local_values .table);298 scattering += CALL_IQ(q, q_index, local_values); 298 299 } 299 300 } … … 301 302 } 302 303 #else // !MAGNETIC 303 const double scattering = CALL_IQ(q, q_index, local_values .table);304 const double scattering = CALL_IQ(q, q_index, local_values); 304 305 #endif // !MAGNETIC 305 306 //printf("q_index:%d %g %g %g %g\n",q_index, scattering, weight, spherical_correction, weight0); -
sasmodels/kernel_iq.cl
rbde38b5 r4f1f876 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 num_eval;// total number of voxels in hypercube25 int32_t num_weights;// total length of the weights vector24 int32_t pd_prod; // total number of voxels in hypercube 25 int32_t pd_sum; // total length of the weights vector 26 26 int32_t num_active; // number of non-trivial pd loops 27 27 int32_t theta_par; // id of spherical correction variable … … 90 90 91 91 // Storage for the current parameter values. These will be updated as we 92 // walk the polydispersity cube. 92 // walk the polydispersity cube. local_values will be aliased to pvec. 93 93 ParameterBlock local_values; 94 95 // Fill in the initial variables 96 for (int i=0; i < NUM_PARS; i++) { 97 local_values.vector[i] = values[2+i]; 98 //if (q_index==0) printf("p%d = %g\n",i, local_values.vector[i]); 99 } 94 100 95 101 #if defined(MAGNETIC) && NUM_MAGNETIC>0 … … 111 117 #endif // MAGNETIC 112 118 113 // Fill in the initial variables 114 // values[0] is scale 115 // values[1] is background 116 for (int i=0; i < NUM_PARS; i++) { 117 local_values.vector[i] = values[2+i]; 118 //if (q_index==0) printf("p%d = %g\n",i, local_values.vector[i]); 119 } 120 //if (q_index==0) printf("NUM_VALUES:%d NUM_PARS:%d MAX_PD:%d\n", NUM_VALUES, NUM_PARS, MAX_PD); 121 //if (q_index==0) printf("start:%d stop:%d\n", pd_start, pd_stop); 122 123 double pd_norm = (pd_start == 0 ? 0.0 : result[nq]); 124 double this_result = (pd_start == 0 ? 0.0 : result[q_index]); 119 double pd_norm, this_result; 120 if (pd_start == 0) { 121 pd_norm = this_result = 0.0; 122 } else { 123 pd_norm = result[nq]; 124 this_result = result[q_index]; 125 } 125 126 //if (q_index==0) printf("start %d %g %g\n", pd_start, pd_norm, this_result); 126 127 127 128 #if MAX_PD>0 128 global const double *pd_value = values + NUM_VALUES ;129 global const double *pd_weight = pd_value + details-> num_weights;129 global const double *pd_value = values + NUM_VALUES + 2; 130 global const double *pd_weight = pd_value + details->pd_sum; 130 131 #endif 131 132 … … 255 256 // TODO: what is the magnetic scattering at q=0 256 257 if (qsq > 1.e-16) { 257 double p[4]; // dd, du, ud, uu258 double p[4]; // spin_i, spin_f 258 259 p[0] = (qy*cos_mspin + qx*sin_mspin)/qsq; 259 260 p[3] = -p[0]; -
sasmodels/kernelcl.py
rbde38b5 r40a87fa 552 552 ] 553 553 #print("Calling OpenCL") 554 # call_details.show(values)554 #print("values",values) 555 555 # Call kernel and retrieve results 556 556 last_call = None 557 557 step = 100 558 for start in range(0, call_details. num_eval, step):559 stop = min(start + step, call_details.num_eval)558 for start in range(0, call_details.pd_prod, step): 559 stop = min(start+step, call_details.pd_prod) 560 560 #print("queuing",start,stop) 561 561 args[1:3] = [np.int32(start), np.int32(stop)] … … 563 563 None, *args, wait_for=last_call)] 564 564 cl.enqueue_copy(self.queue, self.result, self.result_b) 565 #print("result", self.result)566 565 567 566 # Free buffers … … 571 570 scale = values[0]/self.result[self.q_input.nq] 572 571 background = values[1] 573 #print("scale",scale, values[0],self.result[self.q_input.nq])572 #print("scale",scale,background) 574 573 return scale*self.result[:self.q_input.nq] + background 575 574 # return self.result[:self.q_input.nq] -
sasmodels/kerneldll.py
rbde38b5 r40a87fa 380 380 self.real(cutoff), # cutoff 381 381 ] 382 #print("Calling DLL") 383 #call_details.show(values) 382 #print("kerneldll values", values) 384 383 step = 100 385 for start in range(0, call_details. num_eval, step):386 stop = min(start + step, call_details.num_eval)384 for start in range(0, call_details.pd_prod, step): 385 stop = min(start+step, call_details.pd_prod) 387 386 args[1:3] = [start, stop] 387 #print("calling DLL") 388 388 kernel(*args) # type: ignore 389 389 -
sasmodels/kernelpy.py
rbde38b5 r40a87fa 100 100 """ 101 101 def __init__(self, kernel, model_info, q_input): 102 # type: (callable, ModelInfo, List[np.ndarray]) -> None103 102 self.dtype = np.dtype('d') 104 103 self.info = model_info … … 157 156 158 157 def __call__(self, call_details, values, cutoff, magnetic): 159 # type: (CallDetails, np.ndarray, np.ndarray, float, bool) -> np.ndarray 160 if magnetic: 161 raise NotImplementedError("Magnetism not implemented for pure python models") 162 #print("Calling python kernel") 163 #call_details.show(values) 158 assert isinstance(call_details, details.CallDetails) 164 159 res = _loops(self._parameter_vector, self._form, self._volume, 165 160 self.q_input.nq, call_details, values, cutoff) … … 167 162 168 163 def release(self): 169 # type: () -> None170 164 """ 171 165 Free resources associated with the kernel. … … 195 189 return np.ones(nq, 'd')*background 196 190 197 pd_value = values[2+n_pars:2+n_pars + call_details. num_weights]198 pd_weight = values[2+n_pars + call_details. num_weights:]191 pd_value = values[2+n_pars:2+n_pars + call_details.pd_sum] 192 pd_weight = values[2+n_pars + call_details.pd_sum:] 199 193 200 194 pd_norm = 0.0 … … 215 209 216 210 total = np.zeros(nq, 'd') 217 for loop_index in range(call_details. num_eval):211 for loop_index in range(call_details.pd_prod): 218 212 # update polydispersity parameter values 219 213 if p0_index == p0_length: -
sasmodels/mixture.py
rfe496dd r7ae2b7f 11 11 *ProductModel(P, S)*. 12 12 """ 13 from __future__ import print_function14 15 13 from copy import copy 16 14 import numpy as np # type: ignore … … 18 16 from .modelinfo import Parameter, ParameterTable, ModelInfo 19 17 from .kernel import KernelModel, Kernel 20 from .details import make_details21 18 22 19 try: 23 20 from typing import List 21 from .details import CallDetails 24 22 except ImportError: 25 23 pass … … 28 26 # type: (List[ModelInfo]) -> ModelInfo 29 27 """ 30 Create info block for mixturemodel.28 Create info block for product model. 31 29 """ 32 30 flatten = [] … … 40 38 # Build new parameter list 41 39 combined_pars = [] 42 demo = {}43 40 for k, part in enumerate(parts): 44 41 # Parameter prefix per model, A_, B_, ... … … 46 43 # to support vector parameters 47 44 prefix = chr(ord('A')+k) + '_' 48 scale = Parameter(prefix+'scale', default=1.0, 49 description="model intensity for " + part.name) 50 combined_pars.append(scale) 45 combined_pars.append(Parameter(prefix+'scale')) 51 46 for p in part.parameters.kernel_parameters: 52 47 p = copy(p) … … 56 51 p.length_control = prefix + p.length_control 57 52 combined_pars.append(p) 58 demo.update((prefix+k, v) for k, v in part.demo.items()59 if k != "background")60 #print("pars",combined_pars)61 53 parameters = ParameterTable(combined_pars) 62 parameters.max_pd = sum(part.parameters.max_pd for part in parts)63 54 64 55 model_info = ModelInfo() … … 79 70 # Remember the component info blocks so we can build the model 80 71 model_info.composition = ('mixture', parts) 81 model_info.demo = demo82 return model_info83 72 84 73 … … 89 78 self.parts = parts 90 79 91 def make_kernel(self, q_vectors):80 def __call__(self, q_vectors): 92 81 # type: (List[np.ndarray]) -> MixtureKernel 93 82 # Note: may be sending the q_vectors to the n times even though they … … 115 104 self.info = model_info 116 105 self.kernels = kernels 117 self.dtype = self.kernels[0].dtype118 106 119 def __call__(self, call_details, value s, cutoff, magnetic):120 # type: (CallDetails, np.ndarray, np.ndarry, float , bool) -> np.ndarray121 scale, background = value s[0:2]107 def __call__(self, call_details, value, weight, cutoff): 108 # type: (CallDetails, np.ndarray, np.ndarry, float) -> np.ndarray 109 scale, background = value[0:2] 122 110 total = 0.0 123 111 # remember the parts for plotting later 124 112 self.results = [] 125 offset = 2 # skip scale & background 126 parts = MixtureParts(self.info, self.kernels, call_details, values) 127 for kernel, kernel_details, kernel_values in parts: 128 #print("calling kernel", kernel.info.name) 129 result = kernel(kernel_details, kernel_values, cutoff, magnetic) 130 #print(kernel.info.name, result) 131 total += result 132 self.results.append(result) 113 for kernel, kernel_details in zip(self.kernels, call_details.parts): 114 part_result = kernel(kernel_details, value, weight, cutoff) 115 total += part_result 116 self.results.append(part_result) 133 117 134 118 return scale*total + background … … 139 123 k.release() 140 124 141 142 class MixtureParts(object):143 def __init__(self, model_info, kernels, call_details, values):144 # type: (ModelInfo, List[Kernel], CallDetails, np.ndarray) -> None145 self.model_info = model_info146 self.parts = model_info.composition[1]147 self.kernels = kernels148 self.call_details = call_details149 self.values = values150 self.spin_index = model_info.parameters.npars + 2151 #call_details.show(values)152 153 def __iter__(self):154 # type: () -> PartIterable155 self.part_num = 0156 self.par_index = 2157 self.mag_index = self.spin_index + 3158 return self159 160 def next(self):161 # type: () -> Tuple[List[Callable], CallDetails, np.ndarray]162 if self.part_num >= len(self.parts):163 raise StopIteration()164 info = self.parts[self.part_num]165 kernel = self.kernels[self.part_num]166 call_details = self._part_details(info, self.par_index)167 values = self._part_values(info, self.par_index, self.mag_index)168 values = values.astype(kernel.dtype)169 #call_details.show(values)170 171 self.part_num += 1172 self.par_index += info.parameters.npars + 1173 self.mag_index += 3 * len(info.parameters.magnetism_index)174 175 return kernel, call_details, values176 177 def _part_details(self, info, par_index):178 # type: (ModelInfo, int) -> CallDetails179 full = self.call_details180 # par_index is index into values array of the current parameter,181 # which includes the initial scale and background parameters.182 # We want the index into the weight length/offset for each parameter.183 # Exclude the initial scale and background, so subtract two, but each184 # component has its own scale factor which we need to skip when185 # constructing the details for the kernel, so add one, giving a186 # net subtract one.187 index = slice(par_index - 1, par_index - 1 + info.parameters.npars)188 length = full.length[index]189 offset = full.offset[index]190 # The complete weight vector is being sent to each part so that191 # offsets don't need to be adjusted.192 part = make_details(info, length, offset, full.num_weights)193 return part194 195 def _part_values(self, info, par_index, mag_index):196 # type: (ModelInfo, int, int) -> np.ndarray197 #print(info.name, par_index, self.values[par_index:par_index + info.parameters.npars + 1])198 scale = self.values[par_index]199 pars = self.values[par_index + 1:par_index + info.parameters.npars + 1]200 nmagnetic = len(info.parameters.magnetism_index)201 if nmagnetic:202 spin_state = self.values[self.spin_index:self.spin_index + 3]203 mag_index = self.values[mag_index:mag_index + 3 * nmagnetic]204 else:205 spin_state = []206 mag_index = []207 nvalues = self.model_info.parameters.nvalues208 nweights = self.call_details.num_weights209 weights = self.values[nvalues:nvalues+2*nweights]210 zero = self.values.dtype.type(0.)211 values = [[scale, zero], pars, spin_state, mag_index, weights]212 # Pad value array to a 32 value boundary213 spacer = (32 - sum(len(v) for v in values)%32)%32214 values.append([zero]*spacer)215 values = np.hstack(values).astype(self.kernels[0].dtype)216 return values -
sasmodels/sasview_model.py
rbde38b5 rfd19811 24 24 from . import weights 25 25 from . import modelinfo 26 from .details import make_kernel_args, dispersion_mesh26 from .details import build_details, dispersion_mesh 27 27 28 28 try: … … 565 565 parameters = self._model_info.parameters 566 566 pairs = [self._get_weights(p) for p in parameters.call_parameters] 567 call_details, values, is_magnetic = make_kernel_args(calculator, pairs)567 call_details, values, is_magnetic = build_details(calculator, pairs) 568 568 #call_details.show() 569 569 #print("pairs", pairs)
Note: See TracChangeset
for help on using the changeset viewer.