# Home

## 20. Ctypes model evaluator

## `sasmodels.kerneldll`

DLL driver for C kernels

If the environment variable SAS_OPENMP is set, then sasmodels will attempt to compile with OpenMP flags so that the model can use all available kernels. This may or may not be available on your compiler toolchain. Depending on operating system and environment.

Windows does not have provide a compiler with the operating system. Instead, we assume that TinyCC is installed and available. This can be done with a simple pip command if it is not already available:

    pip install tinycc

If Microsoft Visual C++ is available (because VCINSTALLDIR is defined in the environment), then that will be used instead. Microsoft Visual C++ for Python is available from Microsoft:

> http://www.microsoft.com/en-us/download/details.aspx?id=44266

If neither compiler is available, sasmodels will check for MinGW, the GNU compiler toolchain. This available in packages such as Anaconda and PythonXY, or available stand alone. This toolchain has had difficulties on some systems, and may or may not work for you.

You can control which compiler to use by setting SAS_COMPILER in the environment:

> - tinycc (Windows): use the TinyCC compiler shipped with SasView

> - msvc (Windows): use the Microsoft Visual C++ compiler

> - mingw (Windows): use the MinGW GNU cc compiler

> - unix (Linux): use the system cc compiler.

> - unix (Mac): use the clang compiler. You will need XCode installed, and the XCode command line tools. Mac comes with OpenCL drivers, so generally this will not be needed.

Both msvc and mingw require that the compiler is available on your path. For msvc, this can done by running vcvarsall.bat in a windows terminal. Install locations are system dependent, such as:

> C:Program Files (x86)Common FilesMicrosoftVisual C++ for Python9.0vcvarsall.bat

or maybe

> C:UsersyournameAppDataLocalProgramsCommonMicrosoftVisual C++ for Python9.0vcvarsall.bat

OpenMP for msvc requires the Microsoft vcomp90.dll library, which doesn’t seem to be included with the compiler, nor does there appear to be a public download location. There may be one on your machine already in a location such as:

> C:Windowswinsxsx86_microsoft.vc90.openmp*vcomp90.dll

If you copy this to somewhere on your path, such as the python directory or the install directory for this application, then OpenMP should be supported.

For full control of the compiler, define a function compile_command(source,output) which takes the name of the source file and the name of the output file and returns a compile command that can be evaluated in the shell. For even more control, replace the entire compile(source,output) function.

The global attribute ALLOW_SINGLE_PRECISION_DLLS should be set to False if you wish to prevent single precision floating point evaluation for the compiled models, otherwise set it defaults to True.

class sasmodels.kerneldll.DllKernel(kernel: Callable[[], ndarray], model_info: ModelInfo, q_input: PyInput)

  Bases: `Kernel`

  Callable SAS kernel.

  kernel is the c function to call.

  model_info is the module information

  q_input is the DllInput q vectors at which the kernel should be evaluated.

  The resulting call method takes the pars, a list of values for the fixed parameters to the kernel, and pd_pars, a list of (value, weight) vectors for the polydisperse parameters. cutoff determines the integration limits: any points with combined weight less than cutoff will not be calculated.

  Call `release()` when done with the kernel instance.

  Fq(call_details: CallDetails, values: np.ndarray, cutoff: np.ndarray, magnetic: float, radius_effective_mode: bool = 0) → np.ndarray

    Returns <F(q)>, <F(q)^2>, effective radius, shell volume and form:shell volume ratio. The <F(q)> term may be None if the form factor does not support direct computation of \(F(q)\)

    \(P(q) = <F^2(q)>/<V>\) is used for structure factor calculations,

    \[I(q) = \text{scale} \cdot P(q) \cdot S(q) + \text{background}\]

    For the beta approximation, this becomes

    \[I(q) = \text{scale} P (1 + <F>^2/<F^2> (S - 1)) + \text{background} = \text{scale}/<V> (<F^2> + <F>^2 (S - 1)) + \text{background}\]

    \(<F(q)>\) and \(<F^2(q)>\) are averaged by polydispersity in shape and orientation, with each configuration \(x_k\) having form factor \(F(q, x_k)\), weight \(w_k\) and volume \(V_k\). The result is:

    \[P(q)=\frac{\sum w_k F^2(q, x_k) / \sum w_k}{\sum w_k V_k / \sum w_k}\]

    The form factor itself is scaled by volume and contrast to compute the total scattering. This is then squared, and the volume weighted F^2 is then normalized by volume F. For a given density, the number of scattering centers is assumed to scale linearly with volume. Later scaling the resulting \(P(q)\) by the volume fraction of particles gives the total scattering on an absolute scale. Most models incorporate the volume fraction into the overall scale parameter. An exception is vesicle, which includes the volume fraction parameter in the model itself, scaling \(F\) by \(\surd V_f\) so that the math for the beta approximation works out.

    By scaling \(P(q)\) by total weight \(\sum w_k\), there is no need to make sure that the polydisperisity distributions normalize to one. In particular, any distibution values \(x_k\) outside the valid domain of \(F\) will not be included, and the distribution will be implicitly truncated. This is controlled by the parameter limits defined in the model (which truncate the distribution before calling the kernel) as well as any region excluded using the INVALID macro defined within the model itself.

    The volume used in the polydispersity calculation is the form volume for solid objects or the shell volume for hollow objects. Shell volume should be used within \(F\) so that the normalizing scale represents the volume fraction of the shell rather than the entire form. This corresponds to the volume fraction of shell-forming material added to the solvent.

    The calculation of \(S\) requires the effective radius and the volume fraction of the particles. The model can have several different ways to compute effective radius, with the radius_effective_mode parameter used to select amongst them. The volume fraction of particles should be determined from the total volume fraction of the form, not just the shell volume fraction. This makes a difference for hollow shapes, which need to scale the volume fraction by the returned volume ratio when computing \(S\). For solid objects, the shell volume is set to the form volume so this scale factor evaluates to one and so can be used for both hollow and solid shapes.

  Iq(call_details: CallDetails, values: np.ndarray, cutoff: np.ndarray, magnetic: float) → np.ndarray

    Returns I(q) from the polydisperse average scattering.

    \[I(q) = \text{scale} \cdot P(q) + \text{background}\]

    With the correct choice of model and contrast, setting scale to the volume fraction \(V_f\) of particles should match the measured absolute scattering. Some models (e.g., vesicle) have volume fraction built into the model, and do not need an additional scale.

  release() → None

    Release resources associated with the kernel.

  dim = None

    Kernel dimension, either “1d” or “2d”.

  dtype = None

    Numerical precision for the computation.

  info = None

    Model info.

  q_input = None

    Q values at which the kernel is to be evaluated.

  result = None

    Place to hold result of _call_kernel() for subclass.

class sasmodels.kerneldll.DllModel(dllpath: str, model_info: ModelInfo, dtype: dtype = dtype('float32'))

  Bases: `KernelModel`

  ctypes wrapper for a single model.

  dllpath is the stored path to the dll.

  model_info is the model definition returned from `modelinfo.make_model_info()`.

  dtype is the desired model precision. Any numpy dtype for single or double precision floats will do, such as ‘f’, ‘float32’ or ‘single’ for single and ‘d’, ‘float64’ or ‘double’ for double. Double precision is an optional extension which may not be available on all devices.

  Call `release()` when done with the kernel.

  make_kernel(q_vectors: list[ndarray]) → DllKernel

    Instantiate a kernel for evaluating the model at q_vectors.

  release() → None

    Release any resources associated with the model.

  dtype = None
  info = None

sasmodels.kerneldll.compile_command(source, output)

  unix compiler command

sasmodels.kerneldll.compile_model(source: str, output: str) → None

  Compile source producing output.

  Raises RuntimeError if the compile failed or the output wasn’t produced.

sasmodels.kerneldll.decode(s)

sasmodels.kerneldll.dll_name(model_file: str, dtype: dtype) → str

  Name of the dll containing the model. This is the base file name without any path or extension, with a form such as ‘sas_sphere32’.

sasmodels.kerneldll.dll_path(model_file: str, dtype: dtype) → str

  Complete path to the dll for the model. Note that the dll may not exist yet if it hasn’t been compiled.

sasmodels.kerneldll.load_dll(source: str, model_info: ModelInfo, dtype: dtype = dtype('float64')) → DllModel

  Create and load a dll corresponding to the source.

  model_info is the info object returned from `modelinfo.make_model_info()`.

  source is returned from `generate.make_source()`, as make_source(model_info)[‘dll’].

  See `make_dll()` for details on controlling the dll path and the allowed floating point precision.

sasmodels.kerneldll.make_dll(source: str, model_info: ModelInfo, dtype: dtype = dtype('float64'), system: bool = False) → str

  Returns the path to the compiled model defined by kernel_module.

  If the model has not been compiled, or if the source file(s) are newer than the dll, then make_dll will compile the model before returning. This routine does not load the resulting dll.

  dtype is a numpy floating point precision specifier indicating whether the model should be single, double or long double precision. The default is double precision, np.dtype(‘d’).

  Set sasmodels.ALLOW_SINGLE_PRECISION_DLLS to False if single precision models are not allowed as DLLs.

  Set sasmodels.kerneldll.SAS_DLL_PATH to the compiled dll output path. Alternatively, set the environment variable SAS_DLL_PATH. The default is in ~/.sasmodels/compiled_models.

  system is a bool that controls whether these are the precompiled DLLs that would be shipped with a binary distribution.