Changeset baa79c2 in sasmodels
- Timestamp:
- Aug 5, 2016 6:42:44 PM (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:
- cbf4604
- Parents:
- 99f446a
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/details.py
r4f1f876 rbaa79c2 1 """ 2 Kernel Call Details 3 =================== 4 5 When calling sas computational kernels with polydispersity there are a 6 number of details that need to be sent to the caller. This includes the 7 list of polydisperse parameters, the number of points in the polydispersity 8 weight distribution, and which parameter is the "theta" parameter for 9 polar coordinate integration. The :class:`CallDetails` object maintains 10 this data. Use :func:`build_details` to build a *details* object which 11 can be passed to one of the computational kernels. 12 """ 13 1 14 from __future__ import print_function 2 15 … … 24 37 25 38 class CallDetails(object): 39 """ 40 Manage the polydispersity information for the kernel call. 41 42 Conceptually, a polydispersity calculation is an integral over a mesh 43 in n-D space where n is the number of polydisperse parameters. In order 44 to keep the program responsive, and not crash the GPU, only a portion 45 of the mesh is computed at a time. Meshes with a large number of points 46 will therefore require many calls to the polydispersity loop. Restarting 47 a nested loop in the middle requires that the indices of the individual 48 mesh dimensions can be computed for the current loop location. This 49 is handled by the *pd_stride* vector, with n//stride giving the loop 50 index and n%stride giving the position in the sub loops. 51 52 One of the parameters may be the latitude. When integrating in polar 53 coordinates, the total circumference decreases as latitude varies from 54 pi r^2 at the equator to 0 at the pole, and the weight associated 55 with a range of phi values needs to be scaled by this circumference. 56 This scale factor needs to be updated each time the theta value 57 changes. *theta_par* indicates which of the values in the parameter 58 vector is the latitude parameter, or -1 if there is no latitude 59 parameter in the model. In practice, the normalization term cancels 60 if the latitude is not a polydisperse parameter. 61 """ 26 62 parts = None # type: List["CallDetails"] 27 63 def __init__(self, model_info): … … 42 78 43 79 # generate views on different parts of the array 44 self._pd_par 45 self._pd_length 46 self._pd_offset 47 self._pd_stride 80 self._pd_par = self.buffer[0 * max_pd:1 * max_pd] 81 self._pd_length = self.buffer[1 * max_pd:2 * max_pd] 82 self._pd_offset = self.buffer[2 * max_pd:3 * max_pd] 83 self._pd_stride = self.buffer[3 * max_pd:4 * max_pd] 48 84 49 85 # theta_par is fixed … … 51 87 52 88 @property 53 def pd_par(self): return self._pd_par 54 55 @property 56 def pd_length(self): return self._pd_length 57 58 @property 59 def pd_offset(self): return self._pd_offset 60 61 @property 62 def pd_stride(self): return self._pd_stride 63 64 @property 65 def pd_prod(self): return self.buffer[-4] 89 def pd_par(self): 90 """List of polydisperse parameters""" 91 return self._pd_par 92 93 @property 94 def pd_length(self): 95 """Number of weights for each polydisperse parameter""" 96 return self._pd_length 97 98 @property 99 def pd_offset(self): 100 """Offsets for the individual weight vectors in the set of weights""" 101 return self._pd_offset 102 103 @property 104 def pd_stride(self): 105 """Stride in the pd mesh for each pd dimension""" 106 return self._pd_stride 107 108 @property 109 def pd_prod(self): 110 """Total size of the pd mesh""" 111 return self.buffer[-4] 112 66 113 @pd_prod.setter 67 def pd_prod(self, v): self.buffer[-4] = v 68 69 @property 70 def pd_sum(self): return self.buffer[-3] 114 def pd_prod(self, v): 115 self.buffer[-4] = v 116 117 @property 118 def pd_sum(self): 119 """Total length of all the weight vectors""" 120 return self.buffer[-3] 121 71 122 @pd_sum.setter 72 def pd_sum(self, v): self.buffer[-3] = v 73 74 @property 75 def num_active(self): return self.buffer[-2] 123 def pd_sum(self, v): 124 self.buffer[-3] = v 125 126 @property 127 def num_active(self): 128 """Number of active polydispersity loops""" 129 return self.buffer[-2] 130 76 131 @num_active.setter 77 def num_active(self, v): self.buffer[-2] = v 78 79 @property 80 def theta_par(self): return self.buffer[-1] 132 def num_active(self, v): 133 self.buffer[-2] = v 134 135 @property 136 def theta_par(self): 137 """Location of the theta parameter in the parameter vector""" 138 return self.buffer[-1] 139 81 140 @theta_par.setter 82 def theta_par(self, v): self.buffer[-1] = v 141 def theta_par(self, v): 142 self.buffer[-1] = v 83 143 84 144 def show(self): 145 """Print the polydispersity call details to the console""" 85 146 print("num_active", self.num_active) 86 147 print("pd_prod", self.pd_prod) … … 94 155 95 156 def mono_details(model_info): 157 # type: (ModelInfo) -> CallDetails 158 """ 159 Return a :class:`CallDetails` object for a monodisperse calculation 160 of the model defined by *model_info*. 161 """ 96 162 call_details = CallDetails(model_info) 97 163 call_details.pd_prod = 1 … … 105 171 106 172 def poly_details(model_info, weights): 173 """ 174 Return a :class:`CallDetails` object for a polydisperse calculation 175 of the model defined by *model_info* for the given set of *weights*. 176 *weights* is a list of vectors, one for each parameter. Monodisperse 177 parameters should provide a weight vector containing [1.0]. 178 """ 179 # type: (ModelInfo) -> CallDetails 107 180 #print("weights",weights) 108 181 #weights = weights[2:] # Skip scale and background … … 110 183 # Decreasing list of polydispersity lengths 111 184 #print([p.id for p in model_info.parameters.call_parameters]) 112 pd_length = np.array([len(w) for w in weights[2:2+model_info.parameters.npars]]) 185 pd_length = np.array([len(w) 186 for w in weights[2:2+model_info.parameters.npars]]) 113 187 num_active = np.sum(pd_length>1) 114 188 max_pd = model_info.parameters.max_pd … … 137 211 138 212 def dispersion_mesh(model_info, pars): 213 # type: (ModelInfo) -> Tuple[List[np.ndarray], List[np.ndarray]] 139 214 """ 140 215 Create a mesh grid of dispersion parameters and weights. … … 155 230 offset = 0 156 231 for n in lengths: 157 pars.append(np.vstack(value[offset:offset+n]) if n > 1 else value[offset]) 232 pars.append(np.vstack(value[offset:offset+n]) 233 if n > 1 else value[offset]) 158 234 offset += n 159 235 value = pars … … 179 255 data_len = 3*len(scalars) 180 256 extra = ((data_len+31)//32)*32 - data_len 181 data = np.array(scalars+scalars+[1.]*len(scalars)+[0.]*extra, dtype=kernel.dtype) 257 data = np.array(scalars+scalars+[1.]*len(scalars)+[0.]*extra, 258 dtype=kernel.dtype) 182 259 else: 183 260 call_details = poly_details(kernel.info, weights) … … 185 262 data_len = len(scalars) + 2*sum(len(v) for v in values) 186 263 extra = ((data_len+31)//32)*32 - data_len 187 data = np.hstack(scalars+list(values)+list(weights)+[0.]*extra).astype(kernel.dtype) 264 data = np.hstack(scalars+list(values)+list(weights)+[0.]*extra) 265 data = data.astype(kernel.dtype) 188 266 is_magnetic = convert_magnetism(kernel.info.parameters, data) 189 267 #call_details.show() … … 192 270 def convert_magnetism(parameters, values): 193 271 """ 194 Convert magnetism in value tablefrom polar to rectangular coordinates.272 Convert magnetism values from polar to rectangular coordinates. 195 273 196 274 Returns True if any magnetism is present.
Note: See TracChangeset
for help on using the changeset viewer.