Changes in / [6ceca44:d5014e4] in sasmodels
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
.gitignore
re9ed2de r67cc0ff 24 24 /example/Fit_*/ 25 25 /example/batch_fit.csv 26 # Note: changes to gauss20, gauss76 and gauss150 are still tracked since they27 # are part of the repo and required by some models.28 26 /sasmodels/models/lib/gauss*.c -
.travis.yml
r2d09df1 rce8c388 6 6 env: 7 7 - PY=2.7 8 - DEPLOY=True9 8 - os: linux 10 9 env: … … 52 51 on: 53 52 branch: master 54 condition: $DEPLOY = True55 53 notifications: 56 54 slack: -
appveyor.yml
r1258e32 rd810d96 67 67 - cmd: conda install --yes --quiet obvious-ci 68 68 - cmd: conda install --yes --quiet numpy toolchain scipy cython cffi 69 #- cmd: conda install --yes --channel conda-forge pyopencl69 - cmd: conda install --yes --channel conda-forge pyopencl 70 70 - cmd: pip install bumps unittest-xml-reporting tinycc 71 71 -
doc/developer/overview.rst
r2a7e20e r3d40839 185 185 jitter applied before particle orientation. 186 186 187 When computing the orientation dispersity integral, the weights for188 the individual points depends on the map projection used to translate jitter189 angles into latitude/longitude. The choice of projection is set by190 *sasmodels.generate.PROJECTION*, with the default *PROJECTION=1* for191 equirectangular and *PROJECTION=2* for sinusoidal. The more complicated192 Guyou and Postel projections are not implemented. See explore.jitter.draw_mesh193 for details.194 195 187 For numerical integration within form factors etc. sasmodels is mostly using 196 188 Gaussian quadrature with 20, 76 or 150 points depending on the model. It also … … 207 199 Useful testing routines include: 208 200 209 The *sascomp* utility is used to view and compare models with different 210 parameters and calculation engines. The usual case is to simply plot a 211 model that you are developing:: 212 213 python sascomp path/to/model.py 214 215 Once the obvious problems are addressed, check the numerical precision 216 across a variety of randomly generated inputs:: 217 218 python sascomp -engine=single,double path/to/model.py -sets=10 219 220 You can compare different parameter values for the same or different models. 221 For example when looking along the long axis of a cylinder ($\theta=0$), 222 dispersity in $\theta$ should be equivalent to dispersity in $\phi$ 223 when $\phi=90$:: 224 225 python sascomp -2d cylinder theta=0 phi=0,90 theta_pd_type=rectangle \\ 226 phi_pd_type=rectangle phi_pd=10,1 theta_pd=1,10 length=500 radius=10 227 228 It turns out that they are not because the equirectangular map projection 229 weights the points by $\cos(\theta)$ so $\Delta\theta$ is not identical 230 to $\Delta\phi$. Setting *PROJECTION=2* in :mod:`sasmodels.generate` helps 231 somewhat. Postel would help even more in this case, though leading 232 to distortions elsewhere. See :mod:`sasmodels.compare` for many more details. 233 234 *sascomp -ngauss=n* allows you to set the number of quadrature points used 235 for the 1D integration for any model. For example, a carbon nanotube with 236 length 10 $\mu$\ m and radius 1 nm is not computed correctly at high $q$:: 237 238 python sascomp cylinder length=100000 radius=10 -ngauss=76,500 -double -highq 239 240 Note: ticket 702 gives some forms for long rods and thin disks that may 241 be used in place of the integration, depending on $q$, radius and length; if 242 the cylinder model is updated with these corrections then above call will show 243 no difference. 244 245 *explore/check1d.py* uses sasmodels 1D integration and compares that with a 201 :mod:`asymint` a direct implementation of the surface integral for certain 202 models to get a more trusted value for the 1D integral using a 203 reimplementation of the 2D kernel in python and mpmath (which computes math 204 functions to arbitrary precision). It uses $\theta$ ranging from 0 to $\pi$ 205 and $\phi$ ranging from 0 to $2\pi$. It perhaps would benefit from including 206 the U-substitution for $\theta$. 207 208 :mod:`check1d` uses sasmodels 1D integration and compares that with a 246 209 rectangle distribution in $\theta$ and $\phi$, with $\theta$ limits set to 247 210 $\pm 90/\sqrt(3)$ and $\phi$ limits set to $\pm 180/\sqrt(3)$ [The rectangle … … 251 214 similar reasoning.] This should rotate the sample through the entire 252 215 $\theta$-$\phi$ surface according to the pattern that you see in jitter.py when 253 you use 'rectangle' rather than 'gaussian' for its distribution without254 changing the viewing angle. In order to match the 1-D pattern for an arbitrary 255 viewing angle on triaxial shapes, we need to integrate216 you modify it to use 'rectangle' rather than 'gaussian' for its distribution 217 without changing the viewing angle. In order to match the 1-D pattern for 218 an arbitrary viewing angle on triaxial shapes, we need to integrate 256 219 over $\theta$, $\phi$ and $\Psi$. 257 220 258 *sascomp -sphere=n* uses the same rectangular distribution as check1d to 259 compute the pattern of the $q_x$-$q_y$ grid. This ought to produce a 260 spherically symmetric pattern. 261 262 *explore/precision.py* investigates the accuracy of individual functions 263 on the different execution platforms. This includes the basic special 264 functions as well as more complex expressions used in scattering. In many 265 cases the OpenCL function in sasmodels will use a polynomial approximation 266 over part of the range to improve accuracy, as shown in:: 267 268 python explore/precision.py 3j1/x 269 270 *explore/realspace.py* allows you to set up a Monte Carlo simulation of your 271 model by sampling random points within and computing the 1D and 2D scattering 272 patterns. This was used to check the core shell parallelepiped example. This 273 is similar to the general sas calculator in sasview, though it uses different 274 code. 275 276 *explore/jitter.py* is for exploring different options for handling 277 orientation and orientation dispersity. It uses *explore/guyou.py* to 278 generate the Guyou projection. 279 280 *explore/asymint.py* is a direct implementation of the 1D integration for 281 a number of different models. It calculates the integral for a particular 282 $q$ using several different integration schemes, including mpmath with 100 283 bits of precision (33 digits), so you can use it to check the target values 284 for the 1D model tests. This is not a general purpose tool; you will need to 285 edit the file to change the model parameters. It does not currently 286 apply the $u=cos(\theta)$ substitution that many models are using 287 internally so the 76-point gaussian quadrature may not match the value 288 produced by the eqivalent model from sasmodels. 289 290 *explore/symint.py* is for rotationally symmetric models (just cylinder for 291 now), so it can compute an entire curve rather than a single $q$ point. It 292 includes code to compare the long cylinder approximation to cylinder. 293 294 *explore/rpa.py* is for checking different implementations of the RPA model 295 against calculations for specific blends. This is a work in (suspended) 296 progress. 297 298 There are a few modules left over in *explore* that can probably be removed. 299 *angular_pd.py* was an early version of *jitter.py*. *sc.py* and *sc.c* 300 was used to explore different calculations for paracrystal models; it has 301 been absorbed into *asymint.py*. *transform_angles.py* translates orientation 302 parameters from the SasView 3.x definition to sasmodels. 303 304 *explore/angles.py* generates code for the view and jitter transformations. 305 Keep this around since it may be needed if we add new projections. 221 When computing the dispersity integral, weights are scaled by 222 $|\cos(\delta \theta)|$ to account for the points in $\phi$ getting closer 223 together as $\delta \theta$ increases. 224 [This will probably change so that instead of adjusting the weights, we will 225 adjust $\delta\theta$-$\delta\phi$ mesh so that the point density in 226 $\delta\phi$ is lower at larger $\delta\theta$. The flag USE_SCALED_PHI in 227 *kernel_iq.c* selects an alternative algorithm.] 228 229 The integrated dispersion is computed at a set of $(qx, qy)$ points $(q 230 \cos(\alpha), q \sin(\alpha))$ at some angle $\alpha$ (currently angle=0) for 231 each $q$ used in the 1-D integration. The individual $q$ points should be 232 equivalent to asymint rect-n when the viewing angle is set to 233 $(\theta,\phi,\Psi) = (90, 0, 0)$. Such tests can help to validate that 2d 234 models are consistent with 1d models. 235 236 :mod:`sascomp -sphere=n` uses the same rectangular distribution as check1d to 237 compute the pattern of the $q_x$-$q_y$ grid. 238 239 The :mod:`sascomp` utility can be used for 2d as well as 1d calculations to 240 compare results for two sets of parameters or processor types, for example 241 these two oriented cylinders here should be equivalent. 242 243 :mod:`\./sascomp -2d cylinder theta=0 phi=0,90 theta_pd_type=rectangle phi_pd_type=rectangle phi_pd=10,1 theta_pd=1,10 length=500 radius=10` 244 306 245 307 246 Testing -
explore/precision.py
r2a7e20e r2a602c7 345 345 ) 346 346 add_function( 347 name="(1/2 -sin(x)/x+(1-cos(x))/x^2)/x",347 name="(1/2+(1-cos(x))/x^2-sin(x)/x)/x", 348 348 mp_function=lambda x: (0.5 - mp.sin(x)/x + (1-mp.cos(x))/(x*x))/x, 349 349 np_function=lambda x: (0.5 - np.sin(x)/x + (1-np.cos(x))/(x*x))/x, … … 609 609 names = ", ".join(sorted(ALL_FUNCTIONS)) 610 610 print("""\ 611 usage: precision.py [-f/a/r] [-x<range>] "name"...611 usage: precision.py [-f/a/r] [-x<range>] name... 612 612 where 613 613 -f indicates that the function value should be plotted, … … 620 620 zoom indicates linear stepping in [1000, 1010] 621 621 neg indicates linear stepping in [-100.1, 100.1] 622 and name is "all " or one of:622 and name is "all [first]" or one of: 623 623 """+names) 624 624 sys.exit(1) -
explore/realspace.py
r8fb2a94 ra1c32c2 44 44 """ 45 45 return Rx(phi)*Ry(theta)*Rz(psi) 46 47 def apply_view(points, view):48 """49 Apply the view transform (theta, phi, psi) to a set of points.50 51 Points are stored in a 3 x n numpy array.52 53 View angles are in degrees.54 """55 theta, phi, psi = view56 return np.asarray((Rz(phi)*Ry(theta)*Rz(psi))*np.matrix(points.T)).T57 58 59 def invert_view(qx, qy, view):60 """61 Return (qa, qb, qc) for the (theta, phi, psi) view angle at detector62 pixel (qx, qy).63 64 View angles are in degrees.65 """66 theta, phi, psi = view67 q = np.vstack((qx.flatten(), qy.flatten(), 0*qx.flatten()))68 return np.asarray((Rz(-psi)*Ry(-theta)*Rz(-phi))*np.matrix(q))69 70 46 71 47 class Shape: … … 243 219 values = self.value.repeat(points.shape[0]) 244 220 return values, self._adjust(points) 245 246 NUMBA = False247 if NUMBA:248 from numba import njit249 @njit("f8[:](f8[:],f8[:],f8[:],f8[:],f8[:],f8[:],f8[:])")250 def _Iqxy(values, x, y, z, qa, qb, qc):251 Iq = np.zeros_like(qa)252 for j in range(len(Iq)):253 total = 0. + 0j254 for k in range(len(Iq)):255 total += values[k]*np.exp(1j*(qa[j]*x[k] + qb[j]*y[k] + qc[j]*z[k]))256 Iq[j] = abs(total)**2257 return Iq258 259 def calc_Iqxy(qx, qy, rho, points, volume=1.0, view=(0, 0, 0)):260 qx, qy = np.broadcast_arrays(qx, qy)261 qa, qb, qc = invert_view(qx, qy, view)262 rho, volume = np.broadcast_arrays(rho, volume)263 values = rho*volume264 x, y, z = points.T265 266 # I(q) = |sum V(r) rho(r) e^(1j q.r)|^2 / sum V(r)267 if NUMBA:268 Iq = _Iqxy(values, x, y, z, qa.flatten(), qb.flatten(), qc.flatten())269 else:270 Iq = [abs(np.sum(values*np.exp(1j*(qa_k*x + qb_k*y + qc_k*z))))**2271 for qa_k, qb_k, qc_k in zip(qa.flat, qb.flat, qc.flat)]272 return np.asarray(Iq).reshape(qx.shape) / np.sum(volume)273 221 274 222 def _calc_Pr_nonuniform(r, rho, points): … … 291 239 print("processing %d of %d"%(k, len(rho)-1)) 292 240 Pr = extended_Pr[1:-1] 293 return Pr 294 295 def _calc_Pr_uniform(r, rho, points): 241 return Pr / Pr.max() 242 243 def calc_Pr(r, rho, points): 244 # P(r) with uniform steps in r is 3x faster; check if we are uniform 245 # before continuing 246 if np.max(np.abs(np.diff(r) - r[0])) > r[0]*0.01: 247 return _calc_Pr_nonuniform(r, rho, points) 248 296 249 # Make Pr a little be bigger than necessary so that only distances 297 250 # min < d < max end up in Pr 298 dr, n_max = r[0],len(r)251 n_max = len(r) 299 252 extended_Pr = np.zeros(n_max+1, 'd') 300 253 t0 = time.clock() 301 254 t_next = t0 + 3 255 row_zero = np.zeros(len(rho), 'i') 302 256 for k, rho_k in enumerate(rho[:-1]): 303 257 distances = sqrt(np.sum((points[k] - points[k+1:])**2, axis=1)) 304 258 weights = rho_k * rho[k+1:] 305 index = np.minimum(np.asarray(distances/ dr, 'i'), n_max)259 index = np.minimum(np.asarray(distances/r[0], 'i'), n_max) 306 260 # Note: indices may be duplicated, so "Pr[index] += w" will not work!! 307 261 extended_Pr += np.bincount(index, weights, n_max+1) … … 315 269 # we are only accumulating the upper triangular distances. 316 270 #Pr = Pr * 2 / len(rho)**2 317 return Pr 271 return Pr / Pr.max() 318 272 319 273 # Can get an additional 2x by going to C. Cuda/OpenCL will allow even … … 337 291 } 338 292 """ 339 340 if NUMBA:341 @njit("f8[:](f8[:], f8[:], f8[:,:])")342 def _calc_Pr_uniform_jit(r, rho, points):343 dr = r[0]344 n_max = len(r)345 Pr = np.zeros_like(r)346 for j in range(len(rho) - 1):347 x, y, z = points[j, 0], points[j, 1], points[j, 2]348 for k in range(j+1, len(rho)):349 distance = sqrt((x - points[k, 0])**2350 + (y - points[k, 1])**2351 + (z - points[k, 2])**2)352 index = int(distance/dr)353 if index < n_max:354 Pr[index] += rho[j] * rho[k]355 # Make Pr independent of sampling density. The factor of 2 comes because356 # we are only accumulating the upper triangular distances.357 #Pr = Pr * 2 / len(rho)**2358 return Pr359 360 361 def calc_Pr(r, rho, points):362 # P(r) with uniform steps in r is 3x faster; check if we are uniform363 # before continuing364 if np.max(np.abs(np.diff(r) - r[0])) > r[0]*0.01:365 Pr = _calc_Pr_nonuniform(r, rho, points)366 else:367 if NUMBA:368 Pr = _calc_Pr_uniform_jit(r, rho, points)369 else:370 Pr = _calc_Pr_uniform(r, rho, points)371 return Pr / Pr.max()372 373 293 374 294 def j0(x): … … 413 333 plt.legend() 414 334 415 def plot_calc_2d(qx, qy, Iqxy, theory=None):416 import matplotlib.pyplot as plt417 qx, qy = bin_edges(qx), bin_edges(qy)418 #qx, qy = np.meshgrid(qx, qy)419 if theory is not None:420 plt.subplot(121)421 plt.pcolormesh(qx, qy, np.log10(Iqxy))422 plt.xlabel('qx (1/A)')423 plt.ylabel('qy (1/A)')424 if theory is not None:425 plt.subplot(122)426 plt.pcolormesh(qx, qy, np.log10(theory))427 plt.xlabel('qx (1/A)')428 429 335 def plot_points(rho, points): 430 336 import mpl_toolkits.mplot3d … … 437 343 pass 438 344 n = len(points) 439 #print("len points", n) 440 index = np.random.choice(n, size=500) if n > 500 else slice(None, None) 345 index = np.random.choice(n, size=1000) if n > 1000 else slice(None, None) 441 346 ax.scatter(points[index, 0], points[index, 1], points[index, 2], c=rho[index]) 442 347 #low, high = points.min(axis=0), points.max(axis=0) 443 348 #ax.axis([low[0], high[0], low[1], high[1], low[2], high[2]]) 444 349 ax.autoscale(True) 445 446 def check_shape(shape, fn=None):447 rho_solvent = 0448 q = np.logspace(-3, 0, 200)449 r = shape.r_bins(q, r_step=0.01)450 sampling_density = 6*5000 / shape.volume()451 rho, points = shape.sample(sampling_density)452 t0 = time.time()453 Pr = calc_Pr(r, rho-rho_solvent, points)454 print("calc Pr time", time.time() - t0)455 Iq = calc_Iq(q, r, Pr)456 theory = (q, fn(q)) if fn is not None else None457 458 import pylab459 #plot_points(rho, points); pylab.figure()460 plot_calc(r, Pr, q, Iq, theory=theory)461 pylab.show()462 463 def check_shape_2d(shape, fn=None, view=(0, 0, 0)):464 rho_solvent = 0465 nq, qmax = 100, 1.0466 qx = np.linspace(0.0, qmax, nq)467 qy = np.linspace(0.0, qmax, nq)468 Qx, Qy = np.meshgrid(qx, qy)469 sampling_density = 50000 / shape.volume()470 #t0 = time.time()471 rho, points = shape.sample(sampling_density)472 #print("sample time", time.time() - t0)473 t0 = time.time()474 Iqxy = calc_Iqxy(Qx, Qy, rho, points, view=view)475 print("calc time", time.time() - t0)476 theory = fn(Qx, Qy) if fn is not None else None477 Iqxy += 0.001 * Iqxy.max()478 if theory is not None:479 theory += 0.001 * theory.max()480 481 import pylab482 #plot_points(rho, points); pylab.figure()483 plot_calc_2d(qx, qy, Iqxy, theory=theory)484 pylab.show()485 486 def sas_sinx_x(x):487 with np.errstate(all='ignore'):488 retvalue = sin(x)/x489 retvalue[x == 0.] = 1.490 return retvalue491 350 492 351 def sas_2J1x_x(x): … … 514 373 Iq = Iq/Iq[0] 515 374 return Iq 516 517 def cylinder_Iqxy(qx, qy, radius, length, view=(0, 0, 0)):518 qa, qb, qc = invert_view(qx, qy, view)519 qab = np.sqrt(qa**2 + qb**2)520 Fq = sas_2J1x_x(qab*radius) * j0(qc*length/2)521 Iq = Fq**2522 return Iq.reshape(qx.shape)523 375 524 376 def sphere_Iq(q, radius): … … 563 415 return Iq/Iq[0] 564 416 565 def csbox_Iqxy(qx, qy, a, b, c, da, db, dc, slda, sldb, sldc, sld_core, view=(0,0,0)): 566 qa, qb, qc = invert_view(qx, qy, view) 567 568 sld_solvent = 0 569 overlapping = False 570 dr0 = sld_core - sld_solvent 571 drA, drB, drC = slda-sld_solvent, sldb-sld_solvent, sldc-sld_solvent 572 tA, tB, tC = a + 2*da, b + 2*db, c + 2*dc 573 siA = a*sas_sinx_x(a*qa/2) 574 siB = b*sas_sinx_x(b*qb/2) 575 siC = c*sas_sinx_x(c*qc/2) 576 siAt = tA*sas_sinx_x(tA*qa/2) 577 siBt = tB*sas_sinx_x(tB*qb/2) 578 siCt = tC*sas_sinx_x(tC*qc/2) 579 Fq = (dr0*siA*siB*siC 580 + drA*(siAt-siA)*siB*siC 581 + drB*siA*(siBt-siB)*siC 582 + drC*siA*siB*(siCt-siC)) 583 Iq = Fq**2 584 return Iq.reshape(qx.shape) 417 def check_shape(shape, fn=None): 418 rho_solvent = 0 419 q = np.logspace(-3, 0, 200) 420 r = shape.r_bins(q, r_step=0.01) 421 sampling_density = 15000 / shape.volume() 422 rho, points = shape.sample(sampling_density) 423 Pr = calc_Pr(r, rho-rho_solvent, points) 424 Iq = calc_Iq(q, r, Pr) 425 theory = (q, fn(q)) if fn is not None else None 426 427 import pylab 428 #plot_points(rho, points); pylab.figure() 429 plot_calc(r, Pr, q, Iq, theory=theory) 430 pylab.show() 585 431 586 432 def check_cylinder(radius=25, length=125, rho=2.): … … 588 434 fn = lambda q: cylinder_Iq(q, radius, length) 589 435 check_shape(shape, fn) 590 591 def check_cylinder_2d(radius=25, length=125, rho=2., view=(0, 0, 0)):592 shape = EllipticalCylinder(radius, radius, length, rho)593 fn = lambda qx, qy, view=view: cylinder_Iqxy(qx, qy, radius, length, view=view)594 check_shape_2d(shape, fn, view=view)595 596 def check_cylinder_2d_lattice(radius=25, length=125, rho=2.,597 view=(0, 0, 0)):598 nx, dx = 1, 2*radius599 ny, dy = 30, 2*radius600 nz, dz = 30, length601 dx, dy, dz = 2*dx, 2*dy, 2*dz602 def center(*args):603 sigma = 0.333604 space = 2605 return [(space*n+np.random.randn()*sigma)*x for n, x in args]606 shapes = [EllipticalCylinder(radius, radius, length, rho,607 #center=(ix*dx, iy*dy, iz*dz)608 orientation=np.random.randn(3)*0,609 center=center((ix, dx), (iy, dy), (iz, dz))610 )611 for ix in range(nx)612 for iy in range(ny)613 for iz in range(nz)]614 shape = Composite(shapes)615 fn = lambda qx, qy, view=view: cylinder_Iqxy(qx, qy, radius, length, view=view)616 check_shape_2d(shape, fn, view=view)617 436 618 437 def check_sphere(radius=125, rho=2): … … 630 449 side_c2 = copy(side_c).shift(0, 0, -c-dc) 631 450 shape = Composite((core, side_a, side_b, side_c, side_a2, side_b2, side_c2)) 632 def fn(q): 633 return csbox_Iq(q, a, b, c, da, db, dc, slda, sldb, sldc, sld_core) 634 #check_shape(shape, fn) 635 636 view = (20, 30, 40) 637 def fn_xy(qx, qy): 638 return csbox_Iqxy(qx, qy, a, b, c, da, db, dc, 639 slda, sldb, sldc, sld_core, view=view) 640 check_shape_2d(shape, fn_xy, view=view) 451 fn = lambda q: csbox_Iq(q, a, b, c, da, db, dc, slda, sldb, sldc, sld_core) 452 check_shape(shape, fn) 641 453 642 454 if __name__ == "__main__": 643 455 check_cylinder(radius=10, length=40) 644 #check_cylinder_2d(radius=10, length=40, view=(90,30,0))645 #check_cylinder_2d_lattice(radius=10, length=50, view=(90,30,0))646 456 #check_sphere() 647 457 #check_csbox() -
sasmodels/compare.py
r2a7e20e r2d81cfe 92 92 -accuracy=Low accuracy of the resolution calculation Low, Mid, High, Xhigh 93 93 -neval=1 sets the number of evals for more accurate timing 94 -ngauss=0 overrides the number of points in the 1-D gaussian quadrature95 94 96 95 === precision options === -
sasmodels/kernel_iq.c
rec8d4ac r108e70e 174 174 static double 175 175 qac_apply( 176 QACRotation *rotation,176 QACRotation rotation, 177 177 double qx, double qy, 178 178 double *qa_out, double *qc_out) 179 179 { 180 const double dqc = rotation ->R31*qx + rotation->R32*qy;180 const double dqc = rotation.R31*qx + rotation.R32*qy; 181 181 // Indirect calculation of qab, from qab^2 = |q|^2 - qc^2 182 182 const double dqa = sqrt(-dqc*dqc + qx*qx + qy*qy); … … 247 247 static double 248 248 qabc_apply( 249 QABCRotation *rotation,249 QABCRotation rotation, 250 250 double qx, double qy, 251 251 double *qa_out, double *qb_out, double *qc_out) 252 252 { 253 *qa_out = rotation ->R11*qx + rotation->R12*qy;254 *qb_out = rotation ->R21*qx + rotation->R22*qy;255 *qc_out = rotation ->R31*qx + rotation->R32*qy;253 *qa_out = rotation.R11*qx + rotation.R12*qy; 254 *qb_out = rotation.R21*qx + rotation.R22*qy; 255 *qc_out = rotation.R31*qx + rotation.R32*qy; 256 256 } 257 257 … … 454 454 // theta, phi, dtheta, dphi are defined below in projection to avoid repeated code. 455 455 #define BUILD_ROTATION() qac_rotation(&rotation, theta, phi, dtheta, dphi); 456 #define APPLY_ROTATION() qac_apply( &rotation, qx, qy, &qa, &qc)456 #define APPLY_ROTATION() qac_apply(rotation, qx, qy, &qa, &qc) 457 457 #define CALL_KERNEL() CALL_IQ_AC(qa, qc, local_values.table) 458 458 … … 468 468 local_values.table.psi = 0.; 469 469 #define BUILD_ROTATION() qabc_rotation(&rotation, theta, phi, psi, dtheta, dphi, local_values.table.psi) 470 #define APPLY_ROTATION() qabc_apply( &rotation, qx, qy, &qa, &qb, &qc)470 #define APPLY_ROTATION() qabc_apply(rotation, qx, qy, &qa, &qb, &qc) 471 471 #define CALL_KERNEL() CALL_IQ_ABC(qa, qb, qc, local_values.table) 472 472 #elif defined(CALL_IQ_XY) … … 479 479 #endif 480 480 481 // D efine APPLY_PROJECTION depending on model symmetries. We do this outside482 // the previous if block so that we don't need to repeat the identical483 // logic in the IQ_AC and IQ_ABC branches. This will become more important484 // if we implement more projections, or morecomplicated projections.485 #if defined(CALL_IQ) || defined(CALL_IQ_A) // no orientation481 // Doing jitter projection code outside the previous if block so that we don't 482 // need to repeat the identical logic in the IQ_AC and IQ_ABC branches. This 483 // will become more important if we implement more projections, or more 484 // complicated projections. 485 #if defined(CALL_IQ) || defined(CALL_IQ_A) 486 486 #define APPLY_PROJECTION() const double weight=weight0 487 #elif defined(CALL_IQ_XY) // pass orientation to the model487 #elif defined(CALL_IQ_XY) 488 488 // CRUFT: support oriented model which define Iqxy rather than Iqac or Iqabc 489 489 // Need to plug the values for the orientation angles back into parameter … … 515 515 #define APPLY_PROJECTION() const double weight=weight0 516 516 #endif 517 #else // apply jitter and view before calling the model517 #else // !spherosymmetric projection 518 518 // Grab the "view" angles (theta, phi, psi) from the initial parameter table. 519 519 const double theta = values[details->theta_par+2]; … … 526 526 // we go through the mesh. 527 527 double dtheta, dphi, weight; 528 #if PROJECTION == 1 // equirectangular528 #if PROJECTION == 1 529 529 #define APPLY_PROJECTION() do { \ 530 530 dtheta = local_values.table.theta; \ … … 532 532 weight = fabs(cos(dtheta*M_PI_180)) * weight0; \ 533 533 } while (0) 534 #elif PROJECTION == 2 // sinusoidal534 #elif PROJECTION == 2 535 535 #define APPLY_PROJECTION() do { \ 536 536 dtheta = local_values.table.theta; \ … … 542 542 } while (0) 543 543 #endif 544 #endif // done defining APPLY_PROJECTION544 #endif // !spherosymmetric projection 545 545 546 546 // ** define looping macros ** -
sasmodels/models/core_shell_parallelepiped.c
re077231 r108e70e 43 43 // Code converted from functions CSPPKernel and CSParallelepiped in libCylinder.c 44 44 // Did not understand the code completely, it should be rechecked (Miguel Gonzalez) 45 // Code is rewritten, the code is compliant with Diva Singh's thesis now (Dirk Honecker)46 // Code rewritten ; cross checked against hollow rectangular prism and realspace(PAK)45 // Code is rewritten,the code is compliant with Diva Singhs thesis now (Dirk Honecker) 46 // Code rewritten (PAK) 47 47 48 48 const double half_q = 0.5*q; … … 121 121 const double drC = crim_sld-solvent_sld; 122 122 123 // The definitions of ta, tb, tc are not the same as in the 1D case because there is no 124 // the scaling by B. 123 125 const double tA = length_a + 2.0*thick_rim_a; 124 126 const double tB = length_b + 2.0*thick_rim_b; -
sasmodels/models/core_shell_parallelepiped.py
r97be877 r10ee838 136 136 * **Author:** NIST IGOR/DANSE **Date:** pre 2010 137 137 * **Converted to sasmodels by:** Miguel Gonzales **Date:** February 26, 2016 138 * **Last Modified by:** Paul Kienzle **Date:** October 17, 2017 139 * Cross-checked against hollow rectangular prism and rectangular prism for 140 equal thickness overlapping sides, and by Monte Carlo sampling of points 141 within the shape for non-uniform, non-overlapping sides. 138 * **Last Modified by:** Wojciech Potrzebowski **Date:** January 11, 2017 139 * **Currently Under review by:** Paul Butler 142 140 """ 143 141 -
sasmodels/models/lib/gauss150.c
r99b84ec r74768cb 1 // Created by Andrew Jackson on 4/23/07 2 1 /* 2 * GaussWeights.c 3 * SANSAnalysis 4 * 5 * Created by Andrew Jackson on 4/23/07. 6 * Copyright 2007 __MyCompanyName__. All rights reserved. 7 * 8 */ 3 9 #ifdef GAUSS_N 4 10 # undef GAUSS_N … … 10 16 #define GAUSS_W Gauss150Wt 11 17 18 // Note: using array size 152 so that it is a multiple of 4 12 19 13 // Note: using array size 152 rather than 150 so that it is a multiple of 4. 14 // Some OpenCL devices prefer that vectors start and end on nice boundaries. 20 // Gaussians 15 21 constant double Gauss150Z[152]={ 16 22 -0.9998723404457334, … … 164 170 0.9993274305065947, 165 171 0.9998723404457334, 166 0., // zero padding is ignored167 0. // zero padding is ignored172 0., 173 0. 168 174 }; 169 175 … … 319 325 0.0007624720924706, 320 326 0.0003276086705538, 321 0., // zero padding is ignored322 0. // zero padding is ignored327 0., 328 0. 323 329 }; -
sasmodels/models/lib/gauss20.c
r99b84ec r74768cb 1 // Created by Andrew Jackson on 4/23/07 2 1 /* 2 * GaussWeights.c 3 * SANSAnalysis 4 * 5 * Created by Andrew Jackson on 4/23/07. 6 * Copyright 2007 __MyCompanyName__. All rights reserved. 7 * 8 */ 3 9 #ifdef GAUSS_N 4 10 # undef GAUSS_N -
sasmodels/models/lib/gauss76.c
r99b84ec r74768cb 1 // Created by Andrew Jackson on 4/23/07 2 1 /* 2 * GaussWeights.c 3 * SANSAnalysis 4 * 5 * Created by Andrew Jackson on 4/23/07. 6 * Copyright 2007 __MyCompanyName__. All rights reserved. 7 * 8 */ 3 9 #ifdef GAUSS_N 4 10 # undef GAUSS_N
Note: See TracChangeset
for help on using the changeset viewer.