Index: doc/guide/gpu_setup.rst
===================================================================
--- doc/guide/gpu_setup.rst	(revision 63602b15f168fcfb37242dc2e94348a4751243a3)
+++ doc/guide/gpu_setup.rst	(revision 8b31efadb6413d7ae55766f7546c483c7538368e)
@@ -94,4 +94,6 @@
 Device Selection
 ================
+**OpenCL drivers**
+
 If you have multiple GPU devices you can tell the program which device to use.
 By default, the program looks for one GPU and one CPU device from available
@@ -104,8 +106,5 @@
 was used to run the model.
 
-**If you don't want to use OpenCL, you can set** *SAS_OPENCL=None*
-**in your environment settings, and it will only use normal programs.**
-
-If you want to use one of the other devices, you can run the following
+If you want to use a specific driver and devices, you can run the following
 from the python console::
 
@@ -115,5 +114,47 @@
 This will provide a menu of different OpenCL drivers available.
 When one is selected, it will say "set PYOPENCL_CTX=..."
-Use that value as the value of *SAS_OPENCL*.
+Use that value as the value of *SAS_OPENCL=driver:device*.
+
+To use the default OpenCL device (rather than CUDA or None),
+set *SAS_OPENCL=opencl*.
+
+In batch queues, you may need to set *XDG_CACHE_HOME=~/.cache* 
+(Linux only) to a different directory, depending on how the filesystem 
+is configured.  You should also set *SAS_DLL_PATH* for CPU-only modules.
+
+    -DSAS_MODELPATH=path sets directory containing custom models
+    -DSAS_OPENCL=vendor:device|cuda:device|none sets the target GPU device
+    -DXDG_CACHE_HOME=~/.cache sets the pyopencl cache root (linux only)
+    -DSAS_COMPILER=tinycc|msvc|mingw|unix sets the DLL compiler
+    -DSAS_OPENMP=1 turns on OpenMP for the DLLs
+    -DSAS_DLL_PATH=path sets the path to the compiled modules
+
+
+**CUDA drivers**
+
+If OpenCL drivers are not available on your system, but NVidia CUDA
+drivers are available, then set *SAS_OPENCL=cuda* or
+*SAS_OPENCL=cuda:n* for a particular device number *n*.  If no device
+number is specified, then the CUDA drivers looks for look for
+*CUDA_DEVICE=n* or a file ~/.cuda-device containing n for the device number.
+
+In batch queues, the SLURM command *sbatch --gres=gpu:1 ...* will set
+*CUDA_VISIBLE_DEVICES=n*, which ought to set the correct device
+number for *SAS_OPENCL=cuda*.  If not, then set
+*CUDA_DEVICE=$CUDA_VISIBLE_DEVICES* within the batch script.  You may
+need to set the CUDA cache directory to a folder accessible across the
+cluster with *PYCUDA_CACHE_DIR* (or *PYCUDA_DISABLE_CACHE* to disable
+caching), and you may need to set environment specific compiler flags
+with *PYCUDA_DEFAULT_NVCC_FLAGS*.  You should also set *SAS_DLL_PATH* 
+for CPU-only modules.
+
+**No GPU support**
+
+If you don't want to use OpenCL or CUDA, you can set *SAS_OPENCL=None*
+in your environment settings, and it will only use normal programs.
+
+In batch queues, you may need to set *SAS_DLL_PATH* to a directory
+accessible on the compute node.
+
 
 Device Testing
@@ -154,3 +195,3 @@
 *Document History*
 
-| 2017-09-27 Paul Kienzle
+| 2018-10-15 Paul Kienzle
Index: doc/guide/plugin.rst
===================================================================
--- doc/guide/plugin.rst	(revision 57c609bdedf506354431a1f62e27c73c368bb043)
+++ doc/guide/plugin.rst	(revision 81751c29b389be731a04ab84a1a93dedf718e16a)
@@ -291,8 +291,8 @@
 
 **Note: The order of the parameters in the definition will be the order of the
-parameters in the user interface and the order of the parameters in Iq(),
-Iqac(), Iqabc() and form_volume(). And** *scale* **and** *background*
-**parameters are implicit to all models, so they do not need to be included
-in the parameter table.**
+parameters in the user interface and the order of the parameters in Fq(), Iq(),
+Iqac(), Iqabc(), form_volume() and shell_volume().
+And** *scale* **and** *background* **parameters are implicit to all models,
+so they do not need to be included in the parameter table.**
 
 - **"name"** is the name of the parameter shown on the FitPage.
@@ -363,6 +363,6 @@
     scattered intensity.
 
-  - "volume" parameters are passed to Iq(), Iqac(), Iqabc() and form_volume(),
-    and have polydispersity loops generated automatically.
+  - "volume" parameters are passed to Fq(), Iq(), Iqac(), Iqabc(), form_volume()
+    and shell_volume(), and have polydispersity loops generated automatically.
 
   - "orientation" parameters are not passed, but instead are combined with
@@ -492,4 +492,16 @@
 used.
 
+Hollow shapes, where the volume fraction of particle corresponds to the
+material in the shell rather than the volume enclosed by the shape, must
+also define a *shell_volume(par1, par2, ...)* function.  The parameters
+are the same as for *form_volume*.  The *I(q)* calculation should use
+*shell_volume* squared as its scale factor for the volume normalization.
+The structure factor calculation needs *form_volume* in order to properly
+scale the volume fraction parameter, so both functions are required for
+hollow shapes.
+
+Note: Pure python models do not yet support direct computation of the
+average of $F(q)$ and $F^2(q)$.
+
 Embedded C Models
 .................
@@ -503,5 +515,4 @@
 This expands into the equivalent C code::
 
-    #include <math.h>
     double Iq(double q, double par1, double par2, ...);
     double Iq(double q, double par1, double par2, ...)
@@ -512,4 +523,7 @@
 *form_volume* defines the volume of the shape. As in python models, it
 includes only the volume parameters.
+
+*form_volume* defines the volume of the shell for hollow shapes. As in
+python models, it includes only the volume parameters.
 
 **source=['fn.c', ...]** includes the listed C source files in the
@@ -548,4 +562,33 @@
 The INVALID define can go into *Iq*, or *c_code*, or an external C file
 listed in *source*.
+
+Structure Factors
+.................
+
+Structure factor calculations may need the underlying $<F(q)>$ and $<F^2(q)>$
+rather than $I(q)$.  This is used to compute $\beta = <F(q)>^2/<F^2(q)>$ in
+the decoupling approximation to the structure factor.
+
+Instead of defining the *Iq* function, models can define *Fq* as
+something like::
+
+    double Fq(double q, double *F1, double *F2, double par1, double par2, ...);
+    double Fq(double q, double *F1, double *F2, double par1, double par2, ...)
+    {
+        // Polar integration loop over all orientations.
+        ...
+        *F1 = 1e-2 * total_F1 * contrast * volume;
+        *F2 = 1e-4 * total_F2 * square(contrast * volume);
+        return I(q, par1, par2, ...);
+    }
+
+If the volume fraction scale factor is built into the model (as occurs for
+the vesicle model, for example), then scale *F1* by $\surd V_f$ so that
+$\beta$ is computed correctly.
+
+Structure factor calculations are not yet supported for oriented shapes.
+
+Note: only available as a separate C file listed in *source*, or within
+a *c_code* block within the python model definition file.
 
 Oriented Shapes
@@ -1012,10 +1055,11 @@
           "radius": 120., "radius_pd": 0.2, "radius_pd_n":45},
          0.2, 0.228843],
-        [{"radius": 120., "radius_pd": 0.2, "radius_pd_n":45}, "ER", 120.],
-        [{"radius": 120., "radius_pd": 0.2, "radius_pd_n":45}, "VR", 1.],
+        [{"radius": 120., "radius_pd": 0.2, "radius_pd_n":45},
+         0.1, None, None, 120., None, 1.],  # q, F, F^2, R_eff, V, form:shell
+        [{"@S": "hardsphere"}, 0.1, None],
     ]
 
 
-**tests=[[{parameters}, q, result], ...]** is a list of lists.
+**tests=[[{parameters}, q, Iq], ...]** is a list of lists.
 Each list is one test and contains, in order:
 
@@ -1029,7 +1073,13 @@
 - input and output values can themselves be lists if you have several
   $q$ values to test for the same model parameters.
-- for testing *ER* and *VR*, give the inputs as "ER" and "VR" respectively;
-  the output for *VR* should be the sphere/shell ratio, not the individual
-  sphere and shell values.
+- for testing effective radius, volume and form:shell volume ratio, use the
+  extended form of the tests results, with *None, None, R_eff, V, V_r*
+  instead of *Iq*.  This calls the kernel *Fq* function instead of *Iq*.
+- for testing F and F^2 (used for beta approximation) do the same as the
+  effective radius test, but include values for the first two elements,
+  $<F(q)>$ and $<F^2(q)>$.
+- for testing interaction between form factor and structure factor, specify
+  the structure factor name in the parameters as *{"@S": "name", ...}* with
+  the remaining list of parameters defined by the *P@S* product model.
 
 .. _Test_Your_New_Model:
