Changes in / [b26d4c8:119bd3d] in sasmodels


Ignore:
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • doc/developer/index.rst

    rb85be2d r56fc97a  
    33*************************** 
    44 
    5 .. toctree:: 
    6    :numbered: 4 
    7    :maxdepth: 4 
    85 
    9    calculator.rst 
  • sasmodels/core.py

    rcf52f9c r35647ab  
    216216    with an error of about 1%, which is usually less than the measurement 
    217217    uncertainty. 
    218  
    219     *mono* is True if polydispersity should be set to none on all parameters. 
    220     """ 
     218    """ 
     219    print pars 
    221220    fixed_pars = [pars.get(name, kernel.info['defaults'][name]) 
    222221                  for name in kernel.fixed_pars] 
  • sasmodels/kernel_iq.c

    r4b2972c r119bd3d  
    1212*/ 
    1313 
     14/* 
     15The environment needs to provide the following #defines: 
     16 
     17   USE_OPENCL is defined if running in opencl 
     18   KERNEL declares a function to be available externally 
     19   KERNEL_NAME is the name of the function being declared 
     20   NPARS is the number of parameters in the kernel 
     21   PARAMETER_DECL is the declaration of the parameters to the kernel. 
     22 
     23       Cylinder: 
     24 
     25           #define PARAMETER_DECL \ 
     26           double length; \ 
     27           double radius; \ 
     28           double sld; \ 
     29           double sld_solvent 
     30 
     31       Note: scale and background are not included 
     32 
     33       Multi-shell cylinder (10 shell max): 
     34 
     35           #define PARAMETER_DECL \ 
     36           double num_shells; \ 
     37           double length; \ 
     38           double radius[10]; \ 
     39           double sld[10]; \ 
     40           double sld_solvent 
     41 
     42   CALL_IQ(q, nq, i, pars) is the declaration of a call to the kernel. 
     43 
     44       Cylinder: 
     45 
     46           #define CALL_IQ(q, nq, i, var) \ 
     47           Iq(q[i], \ 
     48           var.length, \ 
     49           var.radius, \ 
     50           var.sld, \ 
     51           var.sld_solvent) 
     52 
     53       Multi-shell cylinder: 
     54           #define CALL_IQ(q, nq, i, var) \ 
     55           Iq(q[i], \ 
     56           var.num_shells, \ 
     57           var.length, \ 
     58           var.radius, \ 
     59           var.sld, \ 
     60           var.sld_solvent) 
     61 
     62   CALL_VOLUME(var) is similar, but for calling the form volume. 
     63 
     64   INVALID is a test for model parameters in the correct range 
     65 
     66       Cylinder: 
     67 
     68           #define INVALID(var) 0 
     69 
     70       BarBell: 
     71 
     72           #define INVALID(var) (var.bell_radius > var.radius) 
     73 
     74       Model with complicated constraints: 
     75 
     76           inline bool constrained(p1, p2, p3) { return expression; } 
     77           #define INVALID(var) constrained(var.p1, var.p2, var.p3) 
     78 
     79   IQ_FUNC could be Iq or Iqxy 
     80   IQ_PARS could be q[i] or q[2*i],q[2*i+1] 
     81 
     82Our design supports a limited number of polydispersity loops, wherein 
     83we need to cycle through the values of the polydispersity, calculate 
     84the I(q, p) for each combination of parameters, and perform a normalized 
     85weighted sum across all the weights.  Parameters may be passed to the 
     86underlying calculation engine as scalars or vectors, but the polydispersity 
     87calculator treats the parameter set as one long vector. 
     88 
     89Let's assume we have 6 parameters in the model, with two polydisperse:: 
     90 
     91    0: scale        {scl = constant} 
     92    1: background   {bkg = constant} 
     93    5: length       {l = vector of 30pts} 
     94    4: radius       {r = vector of 10pts} 
     95    3: sld          {s = constant/(radius**2*length)} 
     96    2: sld_solvent  {s2 = constant} 
     97 
     98This generates the following call to the kernel (where x stands for an 
     99arbitrary value that is not used by the kernel evaluator): 
     100 
     101    NPARS = 4  // scale and background are in all models 
     102    problem { 
     103        pd_par = {5, 4, x, x}         // parameters *radius* and *length* vary 
     104        pd_length = {30, 10, 0, 0}    // *length* has more, so it is first 
     105        pd_offset = {10, 0, x, x}     // *length* starts at index 10 in weights 
     106        pd_stride = {1, 30, 300, 300} // cumulative product of pd length 
     107        pd_isvol = {1, 1, x, x}       // true if weight is a volume weight 
     108        par_offset = {2, 3, 303, 313}  // parameter offsets 
     109        par_coord = {0, 3, 2, 1} // bitmap of parameter dependencies 
     110        fast_coord_index = {5, 3, x, x} 
     111        fast_coord_count = 2  // two parameters vary with *length* distribution 
     112        theta_var = -1   // no spherical correction 
     113        fast_theta = 0   // spherical correction angle is not pd 1 
     114    } 
     115 
     116    weight = { l0, .., l29, r0, .., r9} 
     117    pars = { scl, bkg, l0, ..., l29, r0, r1, ..., r9, 
     118             s[l0,r0], ... s[l0,r9], s[l1,r0], ... s[l29,r9] , s2} 
     119 
     120    nq = 130 
     121    q = { q0, q1, ..., q130, x, x }  # pad to 8 element boundary 
     122    result = {r1, ..., r130, norm, vol, vol_norm, x, x, x, x, x, x, x} 
     123 
     124 
     125The polydisperse parameters are stored in as an array of parameter 
     126indices, one for each polydisperse parameter, stored in pd_par[n]. 
     127Non-polydisperse parameters do not appear in this array. Each polydisperse 
     128parameter has a weight vector whose length is stored in pd_length[n], 
     129The weights are stored in a contiguous vector of weights for all 
     130parameters, with the starting position for the each parameter stored 
     131in pd_offset[n].  The values corresponding to the weights are stored 
     132together in a separate weights[] vector, with offset stored in 
     133par_offset[pd_par[n]]. Polydisperse parameters should be stored in 
     134decreasing order of length for highest efficiency. 
     135 
     136We limit the number of polydisperse dimensions to MAX_PD (currently 4). 
     137This cuts the size of the structure in half compared to allowing a 
     138separate polydispersity for each parameter.  This will help a little 
     139bit for models with large numbers of parameters, such as the onion model. 
     140 
     141Parameters may be coordinated.  That is, we may have the value of one 
     142parameter depend on a set of other parameters, some of which may be 
     143polydisperse.  For example, if sld is inversely proportional to the 
     144volume of a cylinder, and the length and radius are independently 
     145polydisperse, then for each combination of length and radius we need a 
     146separate value for the sld.  The caller must provide a coordination table 
     147for each parameter containing the value for each parameter given the 
     148value of the polydisperse parameters v1, v2, etc.  The tables for each 
     149parameter are arranged contiguously in a vector, with offset[k] giving the 
     150starting location of parameter k in the vector.  Each parameter defines 
     151coord[k] as a bit mask indicating which polydispersity parameters the 
     152parameter depends upon. Usually this is zero, indicating that the parameter 
     153is independent, but for the cylinder example given, the bits for the 
     154radius and length polydispersity parameters would both be set, the result 
     155being a (#radius x #length) table, or maybe a (#length x #radius) table 
     156if length comes first in the polydispersity table. 
     157 
     158NB: If we can guarantee that a compiler and OpenCL driver are available, 
     159we could instead create the coordination function on the fly for each 
     160parameter, saving memory and transfer time, but requiring a C compiler 
     161as part of the environment. 
     162 
     163In ordering the polydisperse parameters by decreasing length we can 
     164iterate over the longest dispersion weight vector first.  All parameters 
     165coordinated with this weight vector (the 'fast' parameters), can be 
     166updated with a simple increment to the next position in the parameter 
     167value table.  The indices of these parameters is stored in fast_coord_index[], 
     168with fast_coord_count being the number of fast parameters.  A total 
     169of NPARS slots is allocated to allow for the case that all parameters 
     170are coordinated with the fast index, though this will likely be mostly 
     171empty.  When the fast increment count reaches the end of the weight 
     172vector, then the index of the second polydisperse parameter must be 
     173incremented, and all of its coordinated parameters updated.  Because this 
     174operation is not in the inner loop, a slower algorithm can be used. 
     175 
     176If there is no polydispersity we pretend that it is polydisperisty with one 
     177parameter, pd_start=0 and pd_stop=1.  We may or may not short circuit the 
     178calculation in this case, depending on how much time it saves. 
     179 
     180The problem details structure can be allocated and sent in as an integer 
     181array using the read-only flag.  This allows us to copy it once per fit 
     182along with the weights vector, since features such as the number of 
     183polydisperity elements per pd parameter or the coordinated won't change 
     184between function evaluations.  A new parameter vector is sent for 
     185each I(q) evaluation. 
     186 
     187To protect against expensive evaluations taking all the GPU resource 
     188on large fits, the entire polydispersity will not be computed at once. 
     189Instead, a start and stop location will be sent, indicating where in the 
     190polydispersity loop the calculation should start and where it should 
     191stop.  We can do this for arbitrary start/stop points since we have 
     192unwound the nested loop.  Instead, we use the same technique as array 
     193index translation, using div and mod to figure out the i,j,k,... 
     194indices in the virtual nested loop. 
     195 
     196The results array will be initialized to zero for polydispersity loop 
     197entry zero, and preserved between calls to [start, stop] so that the 
     198results accumulate by the time the loop has completed.  Background and 
     199scale will be applied when the loop reaches the end.  This does require 
     200that the results array be allocated read-write, which is less efficient 
     201for the GPU, but it makes the calling sequence much more manageable. 
     202 
     203Scale and background cannot be coordinated with other polydisperse parameters 
     204 
     205Oriented objects in 2-D need a spherical correction on the angular variation 
     206in order to preserve the 'surface area' of the weight distribution. 
     207 
     208Cutoff specifies the integration area by discarding regions in polydisperisty 
     209hypercubue that has no parameters defined 
     210*/ 
    14211 
    15212#define MAX_PD 4  // MAX_PD is the max number of polydisperse parameters 
     
    34231} ParameterBlock; 
    35232 
    36 #define FULL_KERNEL_NAME KERNEL_NAME ## _ ## IQ_FUNC 
    37 KERNEL 
     233#define KERNEL_NAME test_Iq 
     234#define FULL_KERNEL_NAME test_Iq 
     235#define IQ_FUNC Iq 
     236 
     237 
    38238void FULL_KERNEL_NAME( 
    39239    int nq,                 // number of q values 
     
    204404  } 
    205405} 
     406} 
     407} 
Note: See TracChangeset for help on using the changeset viewer.