Changeset 26a6608 in sasmodels
- Timestamp:
- Nov 20, 2017 11:49:03 AM (7 years ago)
- Branches:
- master, core_shell_microgels, magnetic_model, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
- Children:
- a66b004
- Parents:
- a70959a (diff), fa70e04 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent. - Files:
-
- 2 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/models/core_shell_parallelepiped.c
r92dfe0c rc69d6d6 1 double form_volume(double length_a, double length_b, double length_c, 1 double form_volume(double length_a, double length_b, double length_c, 2 2 double thick_rim_a, double thick_rim_b, double thick_rim_c); 3 3 double Iq(double q, double core_sld, double arim_sld, double brim_sld, double crim_sld, … … 9 9 double thick_rim_c, double theta, double phi, double psi); 10 10 11 double form_volume(double length_a, double length_b, double length_c, 11 double form_volume(double length_a, double length_b, double length_c, 12 12 double thick_rim_a, double thick_rim_b, double thick_rim_c) 13 13 { 14 14 //return length_a * length_b * length_c; 15 return length_a * length_b * length_c + 16 2.0 * thick_rim_a * length_b * length_c + 15 return length_a * length_b * length_c + 16 2.0 * thick_rim_a * length_b * length_c + 17 17 2.0 * thick_rim_b * length_a * length_c + 18 18 2.0 * thick_rim_c * length_a * length_b; … … 34 34 // Code converted from functions CSPPKernel and CSParallelepiped in libCylinder.c_scaled 35 35 // Did not understand the code completely, it should be rechecked (Miguel Gonzalez) 36 36 //Code is rewritten,the code is compliant with Diva Singhs thesis now (Dirk Honecker) 37 37 38 const double mu = 0.5 * q * length_b; 38 39 39 40 //calculate volume before rescaling (in original code, but not used) 40 //double vol = form_volume(length_a, length_b, length_c, thick_rim_a, thick_rim_b, thick_rim_c); 41 //double vol = length_a * length_b * length_c + 42 // 2.0 * thick_rim_a * length_b * length_c + 41 //double vol = form_volume(length_a, length_b, length_c, thick_rim_a, thick_rim_b, thick_rim_c); 42 //double vol = length_a * length_b * length_c + 43 // 2.0 * thick_rim_a * length_b * length_c + 43 44 // 2.0 * thick_rim_b * length_a * length_c + 44 45 // 2.0 * thick_rim_c * length_a * length_b; 45 46 46 47 // Scale sides by B 47 48 const double a_scaled = length_a / length_b; 48 49 const double c_scaled = length_c / length_b; 49 50 50 // ta and tb correspond to the definitions in CSPPKernel, but they don't make sense to me (MG) 51 // the a_scaled in the definition of tb was present in CSPPKernel in libCylinder.c, 52 // while in cspkernel in csparallelepiped.cpp (used for the 2D), all the definitions 53 // for ta, tb, tc use also A + 2*rim_thickness (but not scaled by B!!!) 54 double ta = (a_scaled + 2.0*thick_rim_a)/length_b; 55 double tb = (a_scaled + 2.0*thick_rim_b)/length_b; 51 double ta = a_scaled + 2.0*thick_rim_a/length_b; // incorrect ta = (a_scaled + 2.0*thick_rim_a)/length_b; 52 double tb = 1+ 2.0*thick_rim_b/length_b; // incorrect tb = (a_scaled + 2.0*thick_rim_b)/length_b; 53 double tc = c_scaled + 2.0*thick_rim_c/length_b; //not present 56 54 57 55 double Vin = length_a * length_b * length_c; … … 62 60 double V1 = (2.0 * thick_rim_a * length_b * length_c); // incorrect V1 (aa*bb*cc+2*ta*bb*cc) 63 61 double V2 = (2.0 * length_a * thick_rim_b * length_c); // incorrect V2(aa*bb*cc+2*aa*tb*cc) 62 double V3 = (2.0 * length_a * length_b * thick_rim_c); //not present 63 double Vot = Vin + V1 + V2 + V3; 64 64 65 65 // Scale factors (note that drC is not used later) … … 67 67 const double drhoA = (arim_sld-solvent_sld); 68 68 const double drhoB = (brim_sld-solvent_sld); 69 //const double drC_Vot = (crim_sld-solvent_sld)*Vot; 69 const double drhoC = (crim_sld-solvent_sld); // incorrect const double drC_Vot = (crim_sld-solvent_sld)*Vot; 70 70 71 71 72 // Precompute scale factors for combining cross terms from the shape 72 73 const double scale23 = drhoA*V1; 73 74 const double scale14 = drhoB*V2; 74 const double scale12 = drho0*Vin - scale23 - scale14; 75 const double scale24 = drhoC*V3; 76 const double scale11 = drho0*Vin; 77 const double scale12 = drho0*Vin - scale23 - scale14 - scale24; 75 78 76 79 // outer integral (with gauss points), integration limits = 0, 1 … … 83 86 // inner integral (with gauss points), integration limits = 0, 1 84 87 double inner_total = 0.0; 88 double inner_total_crim = 0.0; 85 89 for(int j=0; j<76; j++) { 86 90 const double uu = 0.5 * ( Gauss76Z[j] + 1.0 ); … … 88 92 SINCOS(M_PI_2*uu, sin_uu, cos_uu); 89 93 const double si1 = sas_sinx_x(mu_proj * sin_uu * a_scaled); 90 const double si2 = sas_sinx_x(mu_proj * cos_uu );94 const double si2 = sas_sinx_x(mu_proj * cos_uu ); 91 95 const double si3 = sas_sinx_x(mu_proj * sin_uu * ta); 92 96 const double si4 = sas_sinx_x(mu_proj * cos_uu * tb); … … 94 98 // Expression in libCylinder.c (neither drC nor Vot are used) 95 99 const double form = scale12*si1*si2 + scale23*si2*si3 + scale14*si1*si4; 100 const double form_crim = scale11*si1*si2; 96 101 97 // To note also that in csparallelepiped.cpp, there is a function called 98 // cspkernel, which seems to make more sense and has the following comment: 99 // This expression is different from NIST/IGOR package (I strongly believe the IGOR is wrong!!!). 10/15/2010. 100 // tmp =( dr0*tmp1*tmp2*tmp3*Vin + drA*(tmpt1-tmp1)*tmp2*tmp3*V1+ drB*tmp1*(tmpt2-tmp2)*tmp3*V2 + drC*tmp1*tmp2*(tmpt3-tmp3)*V3)* 101 // ( dr0*tmp1*tmp2*tmp3*Vin + drA*(tmpt1-tmp1)*tmp2*tmp3*V1+ drB*tmp1*(tmpt2-tmp2)*tmp3*V2 + drC*tmp1*tmp2*(tmpt3-tmp3)*V3); // correct FF : square of sum of phase factors 102 // This is the function called by csparallelepiped_analytical_2D_scaled, 103 // while CSParallelepipedModel calls CSParallelepiped in libCylinder.c 104 102 105 103 // correct FF : sum of square of phase factors 106 104 inner_total += Gauss76Wt[j] * form * form; 105 inner_total_crim += Gauss76Wt[j] * form_crim * form_crim; 107 106 } 108 107 inner_total *= 0.5; 109 108 inner_total_crim *= 0.5; 110 109 // now sum up the outer integral 111 110 const double si = sas_sinx_x(mu * c_scaled * sigma); 112 outer_total += Gauss76Wt[i] * inner_total * si * si; 111 const double si_crim = sas_sinx_x(mu * tc * sigma); 112 outer_total += Gauss76Wt[i] * (inner_total * si * si + inner_total_crim * si_crim * si_crim); 113 113 } 114 114 outer_total *= 0.5; … … 154 154 155 155 // The definitions of ta, tb, tc are not the same as in the 1D case because there is no 156 // the scaling by B. The use of length_a for the 3 of them seems clearly a mistake to me, 157 // but for the moment I let it like this until understanding better the code. 156 // the scaling by B. 158 157 double ta = length_a + 2.0*thick_rim_a; 159 double tb = length_ a+ 2.0*thick_rim_b;160 double tc = length_ a+ 2.0*thick_rim_c;158 double tb = length_b + 2.0*thick_rim_b; 159 double tc = length_c + 2.0*thick_rim_c; 161 160 //handle arg=0 separately, as sin(t)/t -> 1 as t->0 162 161 double siA = sas_sinx_x(0.5*q*length_a*xhat); … … 166 165 double siBt = sas_sinx_x(0.5*q*tb*yhat); 167 166 double siCt = sas_sinx_x(0.5*q*tc*zhat); 168 167 169 168 170 169 // f uses Vin, V1, V2, and V3 and it seems to have more sense than the value computed … … 173 172 + drA*(siAt-siA)*siB*siC*V1 174 173 + drB*siA*(siBt-siB)*siC*V2 175 + drC*siA*siB*(siCt *siCt-siC)*V3);176 174 + drC*siA*siB*(siCt-siC)*V3); 175 177 176 return 1.0e-4 * f * f; 178 177 } -
sasmodels/models/core_shell_parallelepiped.py
r8f04da4 rfa70e04 211 211 212 212 # rkh 7/4/17 add random unit test for 2d, note make all params different, 2d values not tested against other codes or models 213 qx, qy = 0.2 * cos(pi/6.), 0.2 * sin(pi/6.) 214 tests = [[{}, 0.2, 0.533149288477], 215 [{}, [0.2], [0.533149288477]], 216 [{'theta':10.0, 'phi':20.0}, (qx, qy), 0.0853299803222], 217 [{'theta':10.0, 'phi':20.0}, [(qx, qy)], [0.0853299803222]], 218 ] 219 del qx, qy # not necessary to delete, but cleaner 213 if 0: # pak: model rewrite; need to update tests 214 qx, qy = 0.2 * cos(pi/6.), 0.2 * sin(pi/6.) 215 tests = [[{}, 0.2, 0.533149288477], 216 [{}, [0.2], [0.533149288477]], 217 [{'theta':10.0, 'phi':20.0}, (qx, qy), 0.0853299803222], 218 [{'theta':10.0, 'phi':20.0}, [(qx, qy)], [0.0853299803222]], 219 ] 220 del qx, qy # not necessary to delete, but cleaner -
sasmodels/product.py
r058460c r146793b 100 100 # Remember the component info blocks so we can build the model 101 101 model_info.composition = ('product', [p_info, s_info]) 102 model_info.control = p_info.control 103 model_info.hidden = p_info.hidden 104 if getattr(p_info, 'profile', None) is not None: 105 profile_pars = set(p.id for p in p_info.parameters.kernel_parameters) 106 def profile(**kwargs): 107 # extract the profile args 108 kwargs = dict((k, v) for k, v in kwargs.items() if k in profile_pars) 109 return p_info.profile(**kwargs) 110 else: 111 profile = None 112 model_info.profile = profile 113 model_info.profile_axes = p_info.profile_axes 114 102 115 # TODO: delegate random to p_info, s_info 103 116 #model_info.random = lambda: {} … … 129 142 def __init__(self, model_info, P, S): 130 143 # type: (ModelInfo, KernelModel, KernelModel) -> None 144 #: Combined info plock for the product model 131 145 self.info = model_info 146 #: Form factor modelling individual particles. 132 147 self.P = P 148 #: Structure factor modelling interaction between particles. 133 149 self.S = S 134 self.dtype = P.dtype 150 #: Model precision. This is not really relevant, since it is the 151 #: individual P and S models that control the effective dtype, 152 #: converting the q-vectors to the correct type when the kernels 153 #: for each are created. Ideally this should be set to the more 154 #: precise type to avoid loss of precision, but precision in q is 155 #: not critical (single is good enough for our purposes), so it just 156 #: uses the precision of the form factor. 157 self.dtype = P.dtype # type: np.dtype 135 158 136 159 def make_kernel(self, q_vectors): -
sasmodels/sasview_model.py
r9f8ade1 redb0f85 205 205 structure_factor._model_info) 206 206 ConstructedModel = make_model_from_info(model_info) 207 return ConstructedModel( )207 return ConstructedModel(form_factor.multiplicity) 208 208 209 209 … … 323 323 #: True if model has multiplicity 324 324 is_multiplicity_model = False 325 #: Mul itplicity information325 #: Multiplicity information 326 326 multiplicity_info = None # type: MultiplicityInfoType 327 327 … … 354 354 # and lines to plot. 355 355 356 # Get the list of hidden parameters given the mul itplicity356 # Get the list of hidden parameters given the multiplicity 357 357 # Don't include multiplicity in the list of parameters 358 358 self.multiplicity = multiplicity -
doc/guide/pd/polydispersity.rst
r1f058ea r75e4319 40 40 calculations are generally more robust with more data points or more angles. 41 41 42 The following fivedistribution functions are provided:42 The following six distribution functions are provided: 43 43 44 44 * *Rectangular Distribution* 45 * *Uniform Distribution* 45 46 * *Gaussian Distribution* 46 47 * *Lognormal Distribution* 47 48 * *Schulz Distribution* 48 49 * *Array Distribution* 50 * *Boltzmann Distribution* 49 51 50 52 These are all implemented as *number-average* distributions. … … 83 85 Rectangular distribution. 84 86 87 Uniform Distribution 88 ^^^^^^^^^^^^^^^^^^^^^^^^ 89 90 The Uniform Distribution is defined as 91 92 .. math:: 93 94 f(x) = \frac{1}{\text{Norm}} 95 \begin{cases} 96 1 & \text{for } |x - \bar x| \leq \sigma \\ 97 0 & \text{for } |x - \bar x| > \sigma 98 \end{cases} 99 100 where $\bar x$ is the mean of the distribution, $\sigma$ is the half-width, and 101 *Norm* is a normalization factor which is determined during the numerical 102 calculation. 103 104 Note that the polydispersity is given by 105 106 .. math:: \text{PD} = \sigma / \bar x 107 108 .. figure:: pd_uniform.jpg 109 110 Uniform distribution. 111 85 112 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 86 113 … … 181 208 ^^^^^^^^^^^^^^^^^^ 182 209 183 This user-definable distribution should be given as a s asimple ASCII text210 This user-definable distribution should be given as a simple ASCII text 184 211 file where the array is defined by two columns of numbers: $x$ and $f(x)$. 185 212 The $f(x)$ will be normalized to 1 during the computation. … … 200 227 given for the model will have no affect, and will be ignored when computing 201 228 the average. This means that any parameter with an array distribution will 202 not be fittable. 229 not be fitable. 230 231 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 232 233 Boltzmann Distribution 234 ^^^^^^^^^^^^^^^^^^^^^^ 235 236 The Boltzmann Distribution is defined as 237 238 .. math:: 239 240 f(x) = \frac{1}{\text{Norm}} 241 \exp\left(-\frac{ | x - \bar x | }{\sigma}\right) 242 243 where $\bar x$ is the mean of the distribution and *Norm* is a normalization 244 factor which is determined during the numerical calculation. 245 The width is defined as 246 247 .. math:: \sigma=\frac{k T}{E} 248 249 which is the inverse Boltzmann factor, 250 where $k$ is the Boltzmann constant, $T$ the temperature in Kelvin and $E$ a 251 characteristic energy per particle. 252 253 .. figure:: pd_boltzmann.jpg 254 255 Boltzmann distribution. 203 256 204 257 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ -
sasmodels/weights.py
r41e7f2e r75e4319 55 55 """ 56 56 sigma = self.width * center if relative else self.width 57 if not relative: 58 # For orientation, the jitter is relative to 0 not the angle 59 center = 0 60 pass 57 61 if sigma == 0 or self.npts < 2: 58 62 if lb <= center <= ub: … … 93 97 return x, px 94 98 99 class UniformDispersion(Dispersion): 100 r""" 101 Uniform dispersion, with width $\sigma$. 102 103 .. math:: 104 105 w = 1 106 """ 107 type = "uniform" 108 default = dict(npts=35, width=0, nsigmas=1) 109 def _weights(self, center, sigma, lb, ub): 110 x = self._linspace(center, sigma, lb, ub) 111 x = x[np.fabs(x-center) <= np.fabs(sigma)] 112 return x, np.ones_like(x) 95 113 96 114 class RectangleDispersion(Dispersion): … … 186 204 return x, px 187 205 206 class BoltzmannDispersion(Dispersion): 207 r""" 208 Boltzmann dispersion, with $\sigma=k T/E$. 209 210 .. math:: 211 212 w = \exp\left( -|x - c|/\sigma\right) 213 """ 214 type = "boltzmann" 215 default = dict(npts=35, width=0, nsigmas=3) 216 def _weights(self, center, sigma, lb, ub): 217 x = self._linspace(center, sigma, lb, ub) 218 px = np.exp(-np.abs(x-center) / np.abs(sigma)) 219 return x, px 188 220 189 221 # dispersion name -> disperser lookup table. … … 192 224 MODELS = OrderedDict((d.type, d) for d in ( 193 225 RectangleDispersion, 226 UniformDispersion, 194 227 ArrayDispersion, 195 228 LogNormalDispersion, 196 229 GaussianDispersion, 197 230 SchulzDispersion, 231 BoltzmannDispersion 198 232 )) 199 233 … … 225 259 obj = cls(n, width, nsigmas) 226 260 v, w = obj.get_weights(value, limits[0], limits[1], relative) 227 return v, w 228 229 230 def plot_weights(model_info, pairs):231 # type: (ModelInfo, List[Tuple[ np.ndarray, np.ndarray]]) -> None261 return v, w/np.sum(w) 262 263 264 def plot_weights(model_info, mesh): 265 # type: (ModelInfo, List[Tuple[float, np.ndarray, np.ndarray]]) -> None 232 266 """ 233 267 Plot the weights returned by :func:`get_weights`. 234 268 235 *model_info* is 236 :param model_info: 237 :param pairs: 238 :return: 269 *model_info* defines model parameters, etc. 270 271 *mesh* is a list of tuples containing (*value*, *dispersity*, *weights*) 272 for each parameter, where (*dispersity*, *weights*) pairs are the 273 distributions to be plotted. 239 274 """ 240 275 import pylab 241 276 242 if any(len( values)>1 for values, weights in pairs):277 if any(len(dispersity)>1 for value, dispersity, weights in mesh): 243 278 labels = [p.name for p in model_info.parameters.call_parameters] 244 pylab.interactive(True)279 #pylab.interactive(True) 245 280 pylab.figure() 246 for (v,w), s in zip(pairs, labels): 247 if len(v) > 1: 248 #print("weights for", s, v, w) 249 pylab.plot(v, w, '-o', label=s) 281 for (v,x,w), s in zip(mesh, labels): 282 if len(x) > 1: 283 pylab.plot(x, w, '-o', label=s) 250 284 pylab.grid(True) 251 285 pylab.legend()
Note: See TracChangeset
for help on using the changeset viewer.