Changeset 2a7e20e in sasmodels


Ignore:
Timestamp:
Jan 11, 2018 11:02:39 AM (6 years ago)
Author:
Paul Kienzle <pkienzle@…>
Branches:
master, core_shell_microgels, magnetic_model, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
Children:
e077231
Parents:
2ab331f
Message:

update developer docs with current interpretation of orientation; describe the scripts in the explore directory

Files:
4 edited

Legend:

Unmodified
Added
Removed
  • doc/developer/overview.rst

    r3d40839 r2a7e20e  
    185185jitter applied before particle orientation. 
    186186 
     187When computing the orientation dispersity integral, the weights for 
     188the individual points depends on the map projection used to translate jitter 
     189angles into latitude/longitude.  The choice of projection is set by 
     190*sasmodels.generate.PROJECTION*, with the default *PROJECTION=1* for 
     191equirectangular and *PROJECTION=2* for sinusoidal.  The more complicated 
     192Guyou and Postel projections are not implemented. See explore.jitter.draw_mesh 
     193for details. 
     194 
    187195For numerical integration within form factors etc. sasmodels is mostly using 
    188196Gaussian quadrature with 20, 76 or 150 points depending on the model. It also 
     
    199207Useful testing routines include: 
    200208 
    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 
     209The *sascomp* utility is used to view and compare models with different 
     210parameters and calculation engines. The usual case is to simply plot a 
     211model that you are developing:: 
     212 
     213    python sascomp path/to/model.py 
     214 
     215Once the obvious problems are addressed, check the numerical precision 
     216across a variety of randomly generated inputs:: 
     217 
     218    python sascomp -engine=single,double path/to/model.py -sets=10 
     219 
     220You can compare different parameter values for the same or different models. 
     221For example when looking along the long axis of a cylinder ($\theta=0$), 
     222dispersity in $\theta$ should be equivalent to dispersity in $\phi$ 
     223when $\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 
     228It turns out that they are not because the equirectangular map projection 
     229weights the points by $\cos(\theta)$ so $\Delta\theta$ is not identical 
     230to $\Delta\phi$.  Setting *PROJECTION=2* in :mod:`sasmodels.generate` helps 
     231somewhat.  Postel would help even more in this case, though leading 
     232to 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 
     235for the 1D integration for any model.  For example, a carbon nanotube with 
     236length 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 
     240Note: ticket 702 gives some forms for long rods and thin disks that may 
     241be used in place of the integration, depending on $q$, radius and length; if 
     242the cylinder model is updated with these corrections then above call will show 
     243no difference. 
     244 
     245*explore/check1d.py* uses sasmodels 1D integration and compares that with a 
    209246rectangle distribution in $\theta$ and $\phi$, with $\theta$ limits set to 
    210247$\pm 90/\sqrt(3)$ and $\phi$ limits set to $\pm 180/\sqrt(3)$ [The rectangle 
     
    214251similar reasoning.] This should rotate the sample through the entire 
    215252$\theta$-$\phi$ surface according to the pattern that you see in jitter.py when 
    216 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 
     253you use 'rectangle' rather than 'gaussian' for its distribution without 
     254changing the viewing angle. In order to match the 1-D pattern for an arbitrary 
     255viewing angle on triaxial shapes, we need to integrate 
    219256over $\theta$, $\phi$ and $\Psi$. 
    220257 
    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  
     258*sascomp -sphere=n* uses the same rectangular distribution as check1d to 
     259compute the pattern of the $q_x$-$q_y$ grid.  This ought to produce a 
     260spherically symmetric pattern. 
     261 
     262*explore/precision.py* investigates the accuracy of individual functions 
     263on the different execution platforms.  This includes the basic special 
     264functions as well as more complex expressions used in scattering.  In many 
     265cases the OpenCL function in sasmodels will use a polynomial approximation 
     266over 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 
     271model by sampling random points within and computing the 1D and 2D scattering 
     272patterns.  This was used to check the core shell parallelepiped example.  This 
     273is similar to the general sas calculator in sasview, though it uses different 
     274code. 
     275 
     276*explore/jitter.py* is for exploring different options for handling 
     277orientation and orientation dispersity.  It uses *explore/guyou.py* to 
     278generate the Guyou projection. 
     279 
     280*explore/asymint.py* is a direct implementation of the 1D integration for 
     281a number of different models.  It calculates the integral for a particular 
     282$q$ using several different integration schemes, including mpmath with 100 
     283bits of precision (33 digits), so you can use it to check the target values 
     284for the 1D model tests.  This is not a general purpose tool; you will need to 
     285edit the file to change the model parameters. It does not currently 
     286apply the $u=cos(\theta)$ substitution that many models are using 
     287internally so the 76-point gaussian quadrature may not match the value 
     288produced by the eqivalent model from sasmodels. 
     289 
     290*explore/symint.py* is for rotationally symmetric models (just cylinder for 
     291now), so it can compute an entire curve rather than a single $q$ point.  It 
     292includes code to compare the long cylinder approximation to cylinder. 
     293 
     294*explore/rpa.py* is for checking different implementations of the RPA model 
     295against calculations for specific blends.  This is a work in (suspended) 
     296progress. 
     297 
     298There 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* 
     300was used to explore different calculations for paracrystal models; it has 
     301been absorbed into *asymint.py*. *transform_angles.py* translates orientation 
     302parameters from the SasView 3.x definition to sasmodels. 
     303 
     304*explore/angles.py* generates code for the view and jitter transformations. 
     305Keep this around since it may be needed if we add new projections. 
    245306 
    246307Testing 
  • explore/precision.py

    ra1c5758 r2a7e20e  
    345345) 
    346346add_function( 
    347     name="(1/2+(1-cos(x))/x^2-sin(x)/x)/x", 
     347    name="(1/2-sin(x)/x+(1-cos(x))/x^2)/x", 
    348348    mp_function=lambda x: (0.5 - mp.sin(x)/x + (1-mp.cos(x))/(x*x))/x, 
    349349    np_function=lambda x: (0.5 - np.sin(x)/x + (1-np.cos(x))/(x*x))/x, 
     
    609609    names = ", ".join(sorted(ALL_FUNCTIONS)) 
    610610    print("""\ 
    611 usage: precision.py [-f/a/r] [-x<range>] name... 
     611usage: precision.py [-f/a/r] [-x<range>] "name" ... 
    612612where 
    613613    -f indicates that the function value should be plotted, 
     
    620620      zoom indicates linear stepping in [1000, 1010] 
    621621      neg indicates linear stepping in [-100.1, 100.1] 
    622 and name is "all [first]" or one of: 
     622and name is "all" or one of: 
    623623    """+names) 
    624624    sys.exit(1) 
  • sasmodels/compare.py

    ra261a83 r2a7e20e  
    9292    -accuracy=Low accuracy of the resolution calculation Low, Mid, High, Xhigh 
    9393    -neval=1 sets the number of evals for more accurate timing 
     94    -ngauss=0 overrides the number of points in the 1-D gaussian quadrature 
    9495 
    9596    === precision options === 
  • sasmodels/kernel_iq.c

    r108e70e r2a7e20e  
    479479#endif 
    480480 
    481 // 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) 
     481// Define APPLY_PROJECTION depending on model symmetries. We do this outside 
     482// the previous if block so that we don't need to repeat the identical 
     483// logic in the IQ_AC and IQ_ABC branches.  This will become more important 
     484// if we implement more projections, or more complicated projections. 
     485#if defined(CALL_IQ) || defined(CALL_IQ_A)  // no orientation 
    486486  #define APPLY_PROJECTION() const double weight=weight0 
    487 #elif defined(CALL_IQ_XY) 
     487#elif defined(CALL_IQ_XY) // pass orientation to the model 
    488488  // CRUFT: support oriented model which define Iqxy rather than Iqac or Iqabc 
    489489  // Need to plug the values for the orientation angles back into parameter 
     
    515515    #define APPLY_PROJECTION() const double weight=weight0 
    516516  #endif 
    517 #else // !spherosymmetric projection 
     517#else // apply jitter and view before calling the model 
    518518  // Grab the "view" angles (theta, phi, psi) from the initial parameter table. 
    519519  const double theta = values[details->theta_par+2]; 
     
    526526  // we go through the mesh. 
    527527  double dtheta, dphi, weight; 
    528   #if PROJECTION == 1 
     528  #if PROJECTION == 1 // equirectangular 
    529529    #define APPLY_PROJECTION() do { \ 
    530530      dtheta = local_values.table.theta; \ 
     
    532532      weight = fabs(cos(dtheta*M_PI_180)) * weight0; \ 
    533533    } while (0) 
    534   #elif PROJECTION == 2 
     534  #elif PROJECTION == 2 // sinusoidal 
    535535    #define APPLY_PROJECTION() do { \ 
    536536      dtheta = local_values.table.theta; \ 
     
    542542    } while (0) 
    543543  #endif 
    544 #endif // !spherosymmetric projection 
     544#endif // done defining APPLY_PROJECTION 
    545545 
    546546// ** define looping macros ** 
Note: See TracChangeset for help on using the changeset viewer.