# Changeset cddfef6 in sasmodels

Ignore:
Timestamp:
Mar 30, 2019 8:35:15 AM (6 months ago)
Branches:
master, ticket_1156, ticket_822_more_unit_tests
Children:
affc548
Parents:
bc69321 (diff), 9d3a0e5 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of https://github.com/SasView/sasmodels

Files:
87 edited
1 moved

Unmodified
Removed
• ## doc/guide/plugin.rst

 rc94ab04 **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 Fq(), Iq(), Iqac(), Iqabc(), form_volume() and shell_volume(). Iqac(), Iqabc(), radius_effective(), 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.** can take arbitrary values, even for integer parameters, so your model should round the incoming parameter value to the nearest integer inside your model you should round to the nearest integer.  In C code, you can do this using:: you should round to the nearest integer.  In C code, you can do this using: .. code-block:: c static double Models should define *form_volume(par1, par2, ...)* where the parameter list includes the *volume* parameters in order.  This is used for a weighted volume normalization so that scattering is on an absolute scale.  If *form_volume* is not defined, then the default *form_volume = 1.0* will be used. volume normalization so that scattering is on an absolute scale.  For solid shapes, the *I(q)* function should use *form_volume* squared as its scale factor.  If *form_volume* is not defined, then the default *form_volume = 1.0* will be 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. are the same as for *form_volume*.  Here the *I(q)* function should use *shell_volume* squared instead of *form_volume* squared so that the scale parameter corresponds to the volume fraction of material in the sample. The structure factor calculation needs the volume fraction of the filled shapes for its calculation, so the volume fraction parameter in the model is automatically scaled by *form_volume/shell_volume* prior to calling the structure factor. **Note: Pure python models do not yet support direct computation of the** """ This expands into the equivalent C code:: This expands into the equivalent C code: .. code-block:: c double Iq(double q, double par1, double par2, ...); includes only the volume parameters. *form_volume* defines the volume of the shell for hollow shapes. As in *shell_volume* defines the volume of the shell for hollow shapes. As in python models, it includes only the volume parameters. Rather than returning NAN from Iq, you must define the *INVALID(v)*.  The *v* parameter lets you access all the parameters in the model using *v.par1*, *v.par2*, etc. For example:: *v.par1*, *v.par2*, etc. For example: .. code-block:: c #define INVALID(v) (v.bell_radius < v.radius) Instead of defining the *Iq* function, models can define *Fq* as something like:: something like: .. code-block:: c double Fq(double q, double *F1, double *F2, double par1, double par2, ...); laboratory frame and beam travelling along $-z$. The oriented C model (oriented pure Python models are not supported) The oriented C model (oriented pure Python models are not supported) is called using *Iqabc(qa, qb, qc, par1, par2, ...)* where *par1*, etc. are the parameters to the model.  If the shape is rotationally Using the $z, w$ values for Gauss-Legendre integration in "lib/gauss76.c", the numerical integration is then:: numerical integration is then: .. code-block:: c double outer_sum = 0.0; memory, and wrong answers computed. The conclusion from a very long and strange debugging session was that any arrays that you declare in your model should be a multiple of four. For example:: model should be a multiple of four. For example: .. code-block:: c double Iq(q, p1, p2, ...) structure factor is the *hardsphere* interaction, which uses the effective radius of the form factor as an input to the structure factor model.  The effective radius is the average radius of the form averaged over all the polydispersity values. :: def ER(radius, thickness): """Effective radius of a core-shell sphere.""" return radius + thickness Now consider the *core_shell_sphere*, which has a simple effective radius equal to the radius of the core plus the thickness of the shell, as shown above. Given polydispersity over *(r1, r2, ..., rm)* in radius and *(t1, t2, ..., tn)* in thickness, *ER* is called with a mesh grid covering all possible combinations of radius and thickness. That is, *radius* is *(r1, r2, ..., rm, r1, r2, ..., rm, ...)* and *thickness* is *(t1, t1, ... t1, t2, t2, ..., t2, ...)*. The *ER* function returns one effective radius for each combination. The effective radius calculator weights each of these according to the polydispersity distributions and calls the structure factor with the average *ER*. :: def VR(radius, thickness): """Sphere and shell volumes for a core-shell sphere.""" whole = 4.0/3.0 * pi * (radius + thickness)**3 core = 4.0/3.0 * pi * radius**3 return whole, whole - core Core-shell type models have an additional volume ratio which scales the structure factor.  The *VR* function returns the volume of the whole sphere and the volume of the shell. Like *ER*, there is one return value for each point in the mesh grid. *NOTE: we may be removing or modifying this feature soon. As of the time of writing, core-shell sphere returns (1., 1.) for VR, giving a volume ratio of 1.0.* factor model.  The effective radius is the weighted average over all values of the shape in polydisperse systems. There can be many notions of effective radius, depending on the shape.  For a sphere it is clearly just the radius, but for an ellipsoid of revolution we provide average curvature, equivalent sphere radius, minimum radius and maximum radius.  These options are listed as *radius_effective_modes* in the python model defintion, and must be computed by the *radius_effective* function which takes the *radius_effective_mode* parameter as an integer, along with the various model parameters.  Unlike normal C/Python arrays, the first mode is 1, the second is 2, etc.  Mode 0 indicates that the effective radius from the shape is to be ignored in favour of the the effective radius parameter in the structure factor model. Consider the core-shell sphere, which defines the following effective radius modes in the python model:: radius_effective_modes = [ "outer radius", "core radius", ] and the following function in the C-file for the model: .. code-block:: c static double radius_effective(int mode, double radius, double thickness) { switch (mode) { case 0: return radius + thickness; case 1: return radius; default: return 0.; } } static double form_volume(double radius, double thickness) { return M_4PI_3 * cube(radius + thickness); } Given polydispersity over *(r1, r2, ..., rm)* in radius and *(t1, t2, ..., tn)* in thickness, *radius_effective* is called over a mesh grid covering all possible combinations of radius and thickness, with a single *(ri, tj)* pair in each call. The weights each of these results according to the polydispersity distributions and calls the structure factor with the average effective radius.  Similarly, for *form_volume*. Hollow models have an additional volume ratio which is needed to scale the structure factor.  The structure factor uses the volume fraction of the filled particles as part of its density estimate, but the scale factor for the scattering intensity (as non-solvent volume fraction / volume) is determined by the shell volume only.  Therefore the *shell_volume* function is needed to compute the form:shell volume ratio, which then scales the *volfraction* parameter prior to calling the structure factor calculator. In the case of a hollow sphere, this would be: .. code-block:: c static double shell_volume(double radius, double thickness) { double whole = M_4PI_3 * cube(radius + thickness); double core = M_4PI_3 * cube(radius); return whole - core; } If *shell_volume* is not present, then *form_volume* and *shell_volume* are assumed to be equal, and the shape is considered solid. Unit Tests ................... **NB: For now, this more detailed testing is only possible if you have a **NB: For now, this more detailed testing is only possible if you have a SasView build environment available!** | 2016-10-25 Steve King | 2017-05-07 Paul Kienzle - Moved from sasview to sasmodels docs | 2019-03-28 Paul Kienzle - Update docs for radius_effective and shell_volume
• ## doc/guide/resolution.rst

 r8d2df05 .. resolution.rst .. This is a port of the original SasView html help file sm_help to ReSTructured .. This is a port of the original SasView html help file sm_help to ReSTructured .. text by S King, ISIS, during SasView CodeCamp-III in Feb 2015. resolution contribution into a model calculation/simulation (which by definition will be exact) to make it more representative of what has been measured experimentally - a process called *smearing*. The Sasmodels component of SasView experimentally - a process called *smearing*. The Sasmodels component of SasView does the latter. .. note:: Problems may be encountered if the data set loaded by SasView is a concatenation of SANS data from several detector distances where, of course, the worst Q resolution is next to the beam stop at each detector distance. (This will also be noticeable in the residuals plot where there will be poor overlap). SasView sensibly orders all the input data points by increasing Q for nicer-looking plots, however, the dQ data can then vary considerably from point to point. If 'Use dQ data' smearing is selected then spikes may appear in the model fits, whereas Problems may be encountered if the data set loaded by SasView is a concatenation of SANS data from several detector distances where, of course, the worst Q resolution is next to the beam stop at each detector distance. (This will also be noticeable in the residuals plot where there will be poor overlap). SasView sensibly orders all the input data points by increasing Q for nicer-looking plots, however, the dQ data can then vary considerably from point to point. If 'Use dQ data' smearing is selected then spikes may appear in the model fits, whereas if 'None' or 'Custom Pinhole Smear' are selected the fits look normal. In such instances, possible solutions are to simply remove the data with poor Q resolution from the shorter detector distances, or to fit In such instances, possible solutions are to simply remove the data with poor Q resolution from the shorter detector distances, or to fit the data from different detector distances simultaneously.
• ## explore/beta/sasfit_compare.py

 r119073a #radius_effective=12.59921049894873, ) target = sasmodels_theory(q, model, effective_radius_mode=0, structure_factor_mode=1, **pars) target = sasmodels_theory(q, model, radius_effective_mode=0, structure_factor_mode=1, **pars) actual = ellipsoid_pe(q, norm='sasview', **pars) title = " ".join(("sasmodels", model, pd_type))

• ## sasmodels/conversion_table.py

 rfa8e6dc "TwoPowerLawModel", ], "unified_power_rg": [ "unified_power_Rg": [ "UnifiedPowerRg", dict(((field_new+str(index), field_old+str(index))
• ## sasmodels/convert.py

 rfa8e6dc if pars['volfraction_a'] > 0.5: pars['volfraction_a'] = 1.0 - pars['volfraction_a'] elif name == 'unified_power_rg': elif name == 'unified_power_Rg': pars['level'] = int(pars['level'])

• ## sasmodels/direct_model.py

 rb297ba9 """ mesh = get_mesh(calculator.info, pars, dim=calculator.dim, mono=mono) #print("pars", list(zip(*mesh))[0]) #print("in call_kernel: pars:", list(zip(*mesh))[0]) call_details, values, is_magnetic = make_kernel_args(calculator, mesh) #print("values:", values) #print("in call_kernel: values:", values) return calculator(call_details, values, cutoff, is_magnetic) Use parameter *radius_effective_mode* to select the effective radius calculation. calculation to use amongst the *radius_effective_modes* list given in the model. """ R_eff_type = int(pars.pop(RADIUS_MODE_ID, 1.0)) mesh = get_mesh(calculator.info, pars, dim=calculator.dim, mono=mono) #print("pars", list(zip(*mesh))[0]) #print("in call_Fq: pars", list(zip(*mesh))[0]) call_details, values, is_magnetic = make_kernel_args(calculator, mesh) #print("values:", values) #print("in call_Fq: values:", values) return calculator.Fq(call_details, values, cutoff, is_magnetic, R_eff_type) active = lambda name: True #print("pars",[p.id for p in parameters.call_parameters]) #print("in get_mesh: pars:",[p.id for p in parameters.call_parameters]) mesh = [_get_par_weights(p, values, active(p.name)) for p in parameters.call_parameters]

• ## sasmodels/kernelcl.py

 r069743a def _call_kernel(self, call_details, values, cutoff, magnetic, effective_radius_type): radius_effective_mode): # type: (CallDetails, np.ndarray, float, bool, int) -> np.ndarray env = environment() self._result_b,   # Result storage. self._as_dtype(cutoff),  # Probability cutoff. np.uint32(effective_radius_type),  # R_eff mode. np.uint32(radius_effective_mode),  # R_eff mode. ]
• ## sasmodels/kernelcuda.py

 rb297ba9 def _call_kernel(self, call_details, values, cutoff, magnetic, effective_radius_type): radius_effective_mode): # type: (CallDetails, np.ndarray, float, bool, int) -> np.ndarray self._result_b,   # Result storage. self._as_dtype(cutoff),  # Probability cutoff. np.uint32(effective_radius_type),  # R_eff mode. np.uint32(radius_effective_mode),  # R_eff mode. ] grid = partition(self.q_input.nq)
• ## sasmodels/kerneldll.py

 rb297ba9 def _call_kernel(self, call_details, values, cutoff, magnetic, effective_radius_type): radius_effective_mode): # type: (CallDetails, np.ndarray, float, bool, int) -> np.ndarray self.result.ctypes.data,   # Result storage. self._as_dtype(cutoff),  # Probability cutoff. effective_radius_type,  # R_eff mode. radius_effective_mode,  # R_eff mode. ]

• ## sasmodels/model_test.py

 rb297ba9 s_name = pars.pop('@S') ps_test = [pars] + list(test[1:]) #print("PS TEST PARAMS!!!",ps_test) # build the P@S model s_info = load_model_info(s_name) platform=self.platform) # run the tests #self.info = ps_model.info #print("SELF.INFO PARAMS!!!",[p.id for p in self.info.parameters.call_parameters]) #print("PS MODEL PARAMETERS:",[p.id for p in ps_model.info.parameters.call_parameters]) results.append(self.run_one(ps_model, ps_test)) """Run a single test case.""" user_pars, x, y = test[:3] pars = expand_pars(self.info.parameters, user_pars) invalid = invalid_pars(self.info.parameters, pars) #print("PS MODEL PARAMETERS:",[p.id for p in model.info.parameters.call_parameters]) pars = expand_pars(model.info.parameters, user_pars) invalid = invalid_pars(model.info.parameters, pars) if invalid: raise ValueError("Unknown parameters in test: " + ", ".join(invalid)) else: y1 = y y2 = test[3] if not isinstance(test[3], list) else [test[3]] F1, F2, R_eff, volume, volume_ratio = call_Fq(kernel, pars) if F1 is not None:  # F1 is none for models with Iq instead of Fq self._check_vectors(x, y1, F1, 'F') self._check_vectors(x, y2, F2, 'F^2') y2 = test[3] if isinstance(test[3], list) else [test[3]] F, Fsq, R_eff, volume, volume_ratio = call_Fq(kernel, pars) if F is not None:  # F is none for models with Iq instead of Fq self._check_vectors(x, y1, F, 'F') self._check_vectors(x, y2, Fsq, 'F^2') self._check_scalar(test[4], R_eff, 'R_eff') self._check_scalar(test[5], volume, 'volume') self._check_scalar(test[6], volume_ratio, 'form:shell ratio') return F2 return Fsq def _check_scalar(self, target, actual, name): if target is None: # smoke test --- make sure it runs and produces a value self.assertTrue(not np.isnan(actual), 'invalid %s: %s' % (name, actual)) elif np.isnan(target): # make sure nans match self.assertTrue(np.isnan(actual), '%s: expected:%s; actual:%s' % (name, target, actual)) else: # is_near does not work for infinite values, so also test # for exact values. self.assertTrue(target == actual or is_near(target, actual, 5), '%s: expected:%s; actual:%s' % (name, target, actual)) self.assertTrue(is_near(target, actual, 5), '%s: expected:%s; actual:%s' % (name, target, actual)) def _check_vectors(self, x, target, actual, name='I'): '%s(...) returned wrong length'%name) for xi, yi, actual_yi in zip(x, target, actual): if yi is None: # smoke test --- make sure it runs and produces a value self.assertTrue(not np.isnan(actual_yi), 'invalid %s(%s): %s' % (name, xi, actual_yi)) elif np.isnan(yi): # make sure nans match self.assertTrue(np.isnan(actual_yi), '%s(%s): expected:%s; actual:%s' % (name, xi, yi, actual_yi)) else: # is_near does not work for infinite values, so also test # for exact values. self.assertTrue(yi == actual_yi or is_near(yi, actual_yi, 5), '%s(%s); expected:%s; actual:%s' % (name, xi, yi, actual_yi)) self.assertTrue(is_near(yi, actual_yi, 5), '%s(%s): expected:%s; actual:%s' % (name, xi, target, actual)) return ModelTestCase invalid = [] for par in sorted(pars.keys()): # special handling of R_eff mode, which is not a usual parameter # Ignore the R_eff mode parameter when checking for valid parameters. # It is an allowed parameter for a model even though it does not exist # in the parameter table.  The call_Fq() function pops it from the # parameter list and sends it directly to kernel.Fq(). if par == product.RADIUS_MODE_ID: continue """ Returns true if *actual* is within *digits* significant digits of *target*. """ import math shift = 10**math.ceil(math.log10(abs(target))) return abs(target-actual)/shift < 1.5*10**-digits *taget* zero and inf should match *actual* zero and inf.  If you want to accept eps for zero, choose a value such as 1e-10, which must match up to +/- 1e-15 when *digits* is the default value of 5. If *target* is None, then just make sure that *actual* is not NaN. If *target* is NaN, make sure *actual* is NaN. """ if target is None: # target is None => actual cannot be NaN return not np.isnan(actual) elif target == 0.: # target is 0. => actual must be 0. # Note: if small values are allowed, then use maybe test zero against eps instead? return actual == 0. elif np.isfinite(target): shift = np.ceil(np.log10(abs(target))) return abs(target-actual) < 1.5*10**(shift-digits) elif target == actual: # target is inf => actual must be inf of same sign return True else: # target is NaN => actual must be NaN return np.isnan(target) == np.isnan(actual) # CRUFT: old interface; should be deprecated and removed

• ## sasmodels/models/barbell.py

 r0507e09 source = ["lib/polevl.c", "lib/sas_J1.c", "lib/gauss76.c", "barbell.c"] have_Fq = True effective_radius_type = [ radius_effective_modes = [ "equivalent cylinder excluded volume", "equivalent volume sphere", "radius", "half length", "half total length",

• ## sasmodels/models/capped_cylinder.py

 r0507e09 source = ["lib/polevl.c", "lib/sas_J1.c", "lib/gauss76.c", "capped_cylinder.c"] have_Fq = True effective_radius_type = [ radius_effective_modes = [ "equivalent cylinder excluded volume", "equivalent volume sphere", "radius", "half length", "half total length",
• ## sasmodels/models/core_multi_shell.c

 rd42dd4a static double effective_radius(int mode, double core_radius, double fp_n, double thickness[]) radius_effective(int mode, double core_radius, double fp_n, double thickness[]) { switch (mode) {

• ## sasmodels/models/core_shell_bicelle.c

 r99658f6 static double effective_radius(int mode, double radius, double thick_rim, double thick_face, double length) radius_effective(int mode, double radius, double thick_rim, double thick_face, double length) { switch (mode) {
• ## sasmodels/models/core_shell_bicelle.py

 r0507e09 "core_shell_bicelle.c"] have_Fq = True effective_radius_type = [ radius_effective_modes = [ "excluded volume", "equivalent volume sphere", "outer rim radius", "half outer thickness", "half diagonal",
• ## sasmodels/models/core_shell_bicelle_elliptical.c

 r99658f6 static double effective_radius(int mode, double r_minor, double x_core, double thick_rim, double thick_face, double length) radius_effective(int mode, double r_minor, double x_core, double thick_rim, double thick_face, double length) { switch (mode) {
• ## sasmodels/models/core_shell_bicelle_elliptical.py

 r0507e09 "core_shell_bicelle_elliptical.c"] have_Fq = True effective_radius_type = [ radius_effective_modes = [ "equivalent cylinder excluded volume", "equivalent volume sphere", "outer rim average radius", "outer rim min radius",
• ## sasmodels/models/core_shell_bicelle_elliptical_belt_rough.c

 r99658f6 static double effective_radius(int mode, double r_minor, double x_core, double thick_rim, double thick_face, double length) radius_effective(int mode, double r_minor, double x_core, double thick_rim, double thick_face, double length) { switch (mode) {
• ## sasmodels/models/core_shell_bicelle_elliptical_belt_rough.py

 r0507e09 "core_shell_bicelle_elliptical_belt_rough.c"] have_Fq = True effective_radius_type = [ radius_effective_modes = [ "equivalent cylinder excluded volume", "equivalent volume sphere", "outer rim average radius", "outer rim min radius",
• ## sasmodels/models/core_shell_cylinder.c

 r99658f6 static double effective_radius(int mode, double radius, double thickness, double length) radius_effective(int mode, double radius, double thickness, double length) { switch (mode) {
• ## sasmodels/models/core_shell_cylinder.py

 r81d0b9b source = ["lib/polevl.c", "lib/sas_J1.c", "lib/gauss76.c", "core_shell_cylinder.c"] have_Fq = True effective_radius_type = [ radius_effective_modes = [ "excluded volume", "equivalent volume sphere", "outer radius", "half outer length", "half min outer dimension", "half max outer dimension", "half outer diagonal",

• ## sasmodels/models/core_shell_ellipsoid.py

 re5a8f33 ---------- Parameters for this model are the core axial ratio $X_{core}$ and a shell thickness $t_{shell}$, which are more often what we would like to determine and make the model better behaved, particularly when polydispersity is applied, than the four independent radii used in the original parameterization Parameters for this model are the core axial ratio $X_{core}$ and a shell thickness $t_{shell}$, which are more often what we would like to determine and make the model better behaved, particularly when polydispersity is applied, than the four independent radii used in the original parameterization of this model. $X_{core}$ = 1 is a spherical core. For a fixed shell thickness $X_{polar shell}$ = 1, to scale $t_{shell}$ For a fixed shell thickness $X_{polar shell}$ = 1, to scale $t_{shell}$ pro-rata with the radius set or constrain $X_{polar shell}$ = $X_{core}$. .. In following equation SK changed radius\_equat\_core to R_e .. math:: :nowrap: $V = (4/3)\pi R_pR_e^2$ is the volume of the ellipsoid , $R_p$ is the polar radius along the rotational axis of the ellipsoid, $R_e$ is the equatorial radius perpendicular to the rotational axis of the ellipsoid, $t_{shell}$ is the thickness of the shell at the equator, equatorial radius perpendicular to the rotational axis of the ellipsoid, $t_{shell}$ is the thickness of the shell at the equator, and $\Delta \rho$ (the contrast) is the scattering length density difference, either $(\rho_{core} - \rho_{shell})$ or $(\rho_{shell} - \rho_{solvent})$. source = ["lib/sas_3j1x_x.c", "lib/gauss76.c", "core_shell_ellipsoid.c"] have_Fq = True effective_radius_type = [ radius_effective_modes = [ "average outer curvature", "equivalent volume sphere", "min outer radius", "max outer radius",
• ## sasmodels/models/core_shell_parallelepiped.c

 r99658f6 static double effective_radius(int mode, double length_a, double length_b, double length_c, radius_effective(int mode, double length_a, double length_b, double length_c, double thick_rim_a, double thick_rim_b, double thick_rim_c) {
• ## sasmodels/models/core_shell_parallelepiped.py

 r0507e09 source = ["lib/gauss76.c", "core_shell_parallelepiped.c"] have_Fq = True effective_radius_type = [ radius_effective_modes = [ "equivalent cylinder excluded volume", "equivalent volume sphere",

• ## sasmodels/models/ellipsoid.py

 r0507e09 source = ["lib/sas_3j1x_x.c", "lib/gauss76.c", "ellipsoid.c"] have_Fq = True effective_radius_type = [ radius_effective_modes = [ "average curvature", "equivalent volume sphere", "min radius", "max radius", ]
• ## sasmodels/models/elliptical_cylinder.c

 r99658f6 static double effective_radius(int mode, double radius_minor, double r_ratio, double length) radius_effective(int mode, double radius_minor, double r_ratio, double length) { switch (mode) {
• ## sasmodels/models/elliptical_cylinder.py

 r0507e09 source = ["lib/polevl.c", "lib/sas_J1.c", "lib/gauss76.c", "elliptical_cylinder.c"] have_Fq = True effective_radius_type = [ radius_effective_modes = [ "equivalent cylinder excluded volume", "equivalent volume sphere", "average radius", "min radius", "max radius",
• ## sasmodels/models/flexible_cylinder.py

 r40c9825 and solvent respectively. Our model uses the form factor calculations in reference [1] as implemented in a Our model uses the form factor calculations in reference [1] as implemented in a c-library provided by the NIST Center for Neutron Research (Kline, 2006). This states: pseudocontinuous limit. See equations (13,26-27) in the original reference for the details. .. note:: **This is a model with complex behaviour depending on the ratio of** $L/b$ **and the **This is a model with complex behaviour depending on the ratio of** $L/b$ **and the reader is strongly encouraged to read reference [1] before use.** .. note:: There are several typos in the original reference that have been corrected by WRC [2]. Details of the corrections are in the reference below. Most notably - Equation (13): the term $(1 - w(QR))$ should swap position with $w(QR)$ - Equations (23) and (24) are incorrect; WRC has entered these into Mathematica and solved analytically. The results were then converted to code. - Equation (27) should be $q0 = max(a3/(Rg^2)^{1/2},3)$ instead of $max(a3*b(Rg^2)^{1/2},3)$ - The scattering function is negative for a range of parameter values and q-values that are experimentally accessible. A correction function has been added to give the proper behavior. **This is a model with complex behaviour depending on the ratio of** $L/b$ **and the reader is strongly encouraged to read reference [1] before use.** ---------------------------- * **Author:** * **Last Modified by:** * **Author:** * **Last Modified by:** * **Last Reviewed by:** Steve King **Date:** March 26, 2019 * **Source added by :** Steve King **Date:** March 25, 2019
• ## sasmodels/models/flexible_cylinder_elliptical.py

 r40c9825 ----------- The function is calculated in a similar way to that for the :ref:flexible-cylinder model in reference [1] below using the author's The function is calculated in a similar way to that for the :ref:flexible-cylinder model in reference [1] below using the author's "Method 3 With Excluded Volume". these parameters must be held fixed during model fitting. **This is a model with complex behaviour depending on the ratio of** $L/b$ **and the **This is a model with complex behaviour depending on the ratio of** $L/b$ **and the reader is strongly encouraged to read reference [1] before use.** ---------------------------- * **Author:** * **Author:** * **Last Modified by:** Richard Heenan **Date:** December, 2016 * **Last Reviewed by:** Steve King **Date:** March 26, 2019

• ## sasmodels/models/hardsphere.py

 r5f3c534 Calculates the interparticle structure factor for monodisperse spherical particles interacting through hard sphere (excluded volume) interactions. This $S(q)$ may also be a reasonable approximation for other particle shapes that freely rotate (but see the note below), interactions. This $S(q)$ may also be a reasonable approximation for other particle shapes that freely rotate (but see the note below), and for moderately polydisperse systems. .. note:: This routine is intended for uncharged particles! For charged This routine is intended for uncharged particles! For charged particles try using the :ref:hayter-msa $S(q)$ instead. .. note:: Earlier versions of SasView did not incorporate the so-called $\beta(q)$ ("beta") correction [1] for polydispersity and non-sphericity. Earlier versions of SasView did not incorporate the so-called $\beta(q)$ ("beta") correction [1] for polydispersity and non-sphericity. This is only available in SasView versions 4.2.2 and higher. For numerical stability the computation uses a Taylor series expansion at very small $qR$, but there may be a very minor glitch at the at very small $qR$, but there may be a very minor glitch at the transition point in some circumstances. This S(q) uses the Percus-Yevick closure relationship [2] where the This S(q) uses the Percus-Yevick closure relationship [2] where the interparticle potential $U(r)$ is ---------------------------- * **Author:** * **Last Modified by:** * **Last Reviewed by:** * **Author:** * **Last Modified by:** * **Last Reviewed by:** * **Source added by :** Steve King **Date:** March 25, 2019 """
• ## sasmodels/models/hayter_msa.py

 r9947865 # Note: model title and parameter table are inserted automatically r""" Calculates the interparticle structure factor for a system of charged, spheroidal, objects in a dielectric medium [1,2]. When combined with an appropriate form factor $P(q)$, this allows for inclusion of the interparticle interference effects due to screened Coulombic Calculates the interparticle structure factor for a system of charged, spheroidal, objects in a dielectric medium [1,2]. When combined with an appropriate form factor $P(q)$, this allows for inclusion of the interparticle interference effects due to screened Coulombic repulsion between the charged particles. .. note:: This routine only works for charged particles! If the charge is set to zero the routine may self-destruct! For uncharged particles use This routine only works for charged particles! If the charge is set to zero the routine may self-destruct! For uncharged particles use the :ref:hardsphere $S(q)$ instead. The upper limit for the charge is limited to 200e to avoid numerical instabilities. .. note:: Earlier versions of SasView did not incorporate the so-called $\beta(q)$ ("beta") correction [3] for polydispersity and non-sphericity. Earlier versions of SasView did not incorporate the so-called $\beta(q)$ ("beta") correction [3] for polydispersity and non-sphericity. This is only available in SasView versions 4.2.2 and higher. The salt concentration is used to compute the ionic strength of the solution which in turn is used to compute the Debye screening length. There is no provision for entering the ionic strength directly. **At present the counterions are assumed to be monovalent**, though it should be possible to simulate the effect of multivalent counterions by increasing the salt which in turn is used to compute the Debye screening length. There is no provision for entering the ionic strength directly. **At present the counterions are assumed to be monovalent**, though it should be possible to simulate the effect of multivalent counterions by increasing the salt concentration. Over the range 0 - 100 C the dielectric constant $\kappa$ of water may be approximated with a maximum deviation of 0.01 units by the empirical Over the range 0 - 100 C the dielectric constant $\kappa$ of water may be approximated with a maximum deviation of 0.01 units by the empirical formula [4] \kappa = 87.740 - 0.40008 T + 9.398x10^{-4} T^2 - 1.410x10^{-6} T^3 where $T$ is the temperature in celsius. ---------------------------- * **Author:** * **Last Modified by:** * **Author:** * **Last Modified by:** * **Last Reviewed by:** Steve King **Date:** March 28, 2019 * **Source added by :** Steve King **Date:** March 25, 2019 [Hayter-Penfold RMSA charged sphere interparticle S(Q) structure factor] Interparticle structure factor S(Q) for charged hard spheres. This routine only works for charged particles! For uncharged particles use the hardsphere S(q) instead. The "beta(q)" correction is available This routine only works for charged particles! For uncharged particles use the hardsphere S(q) instead. The "beta(q)" correction is available in versions 4.2.2 and higher. """ #             [ "name", "units", default, [lower, upper], "type", "description" ], # # NOTE: SMK, 28Mar19 The upper limit for charge is set to 200 to avoid instabilities noted by PK in #       Ticket #1152. Also see the thread in Ticket 859. The docs above also note that charge=0 will # NOTE: SMK, 28Mar19 The upper limit for charge is set to 200 to avoid instabilities noted by PK in #       Ticket #1152. Also see the thread in Ticket 859. The docs above also note that charge=0 will #       cause problems, yet the default parameters allowed it! After discussions with PK I have #       changed it to (an arbitarily) small but non-zero value.  But I haven't changed the low limit #       changed it to (an arbitarily) small but non-zero value.  But I haven't changed the low limit #       in function random() below. #
• ## sasmodels/models/hollow_cylinder.c

 r99658f6 static double effective_radius(int mode, double radius, double thickness, double length) radius_effective(int mode, double radius, double thickness, double length) { switch (mode) {
• ## sasmodels/models/hollow_cylinder.py

 r0507e09 source = ["lib/polevl.c", "lib/sas_J1.c", "lib/gauss76.c", "hollow_cylinder.c"] have_Fq = True effective_radius_type = [ radius_effective_modes = [ "excluded volume", "equivalent outer volume sphere", "outer radius", "half length",
• ## sasmodels/models/hollow_rectangular_prism.c

 r99658f6 static double effective_radius(int mode, double length_a, double b2a_ratio, double c2a_ratio, double thickness) radius_effective(int mode, double length_a, double b2a_ratio, double c2a_ratio, double thickness) // NOTE length_a is external dimension! {
• ## sasmodels/models/hollow_rectangular_prism.py

 r0507e09 source = ["lib/gauss76.c", "hollow_rectangular_prism.c"] have_Fq = True effective_radius_type = [ radius_effective_modes = [ "equivalent cylinder excluded volume", "equivalent outer volume sphere", "half length_a", "half length_b", "half length_c",
• ## sasmodels/models/hollow_rectangular_prism_thin_walls.c

 r99658f6 static double effective_radius(int mode, double length_a, double b2a_ratio, double c2a_ratio) radius_effective(int mode, double length_a, double b2a_ratio, double c2a_ratio) { switch (mode) {
• ## sasmodels/models/hollow_rectangular_prism_thin_walls.py

 r0507e09 source = ["lib/gauss76.c", "hollow_rectangular_prism_thin_walls.c"] have_Fq = True effective_radius_type = [ radius_effective_modes = [ "equivalent cylinder excluded volume", "equivalent outer volume sphere", "half length_a", "half length_b", "half length_c",
• ## sasmodels/models/mono_gauss_coil.c

 r153f8f6 static double effective_radius(int mode, double rg) radius_effective(int mode, double rg) { switch (mode) {
• ## sasmodels/models/mono_gauss_coil.py

 r0507e09 ---------------------------- * **Author:** * **Last Modified by:** * **Last Reviewed by:** * **Author:** * **Last Modified by:** * **Last Reviewed by:** * **Source added by :** Steve King **Date:** March 25, 2019""" source = ["mono_gauss_coil.c"] have_Fq = False effective_radius_type = ["R_g", "2R_g", "3R_g", "sqrt(5/3)*R_g"] radius_effective_modes = ["R_g", "2R_g", "3R_g", "sqrt(5/3)*R_g"]
• ## sasmodels/models/multilayer_vesicle.c

 ree60aa7 static double effective_radius(int mode, double radius, double thick_shell, double thick_solvent, double fp_n_shells) radius_effective(int mode, double radius, double thick_shell, double thick_solvent, double fp_n_shells) { // case 1: outer radius

• ## sasmodels/models/onion.py

 r62dc889 .. note:: *radius* represents the core radius $r_0$ and *thickness[k]* represents *radius* represents the core radius $r_0$ and *thickness[k]* represents the thickness of the shell, $r_{k+1} - r_k$. and the volume is $V(r) = \frac{4\pi}{3}r^3$. The volume of the particle is determined by the radius of the outer The volume of the particle is determined by the radius of the outer shell, so $V_\text{particle} = V(r_N)$. B&=\frac{\rho_\text{out} - \rho_\text{in}}{e^A-1} & C &= \frac{\rho_\text{in}e^A - \rho_\text{out}}{e^A-1} \\ \alpha_\text{in} &= A\frac{r_{\text{shell}-1}}{\Delta t_\text{shell}} & \alpha_\text{out} &= A\frac{r_\text{shell}}{\Delta t_\text{shell}} \\ \beta_\text{in} &= qr_{\text{shell}-1} & \beta_\text{out} &= qr_\text{shell} \\ **Linear SLD profile** ($A \sim 0$): For small $A$, say, $A = -0.0001$, the function converges to that of of a linear For small $A$, say, $A = -0.0001$, the function converges to that of of a linear SLD profile with **Constant SLD** ($A = 0$): When $A = 0$ the exponential function has no dependence on the radius (meaning When $A = 0$ the exponential function has no dependence on the radius (meaning $\rho_\text{out}$ is ignored in this case) and becomes flat. We set the constant to $\rho_\text{in}$ for convenience, and thus the form factor contributed by ---------------------------- * **Author:** * **Last Modified by:** * **Author:** * **Last Modified by:** * **Last Reviewed by:** Steve King **Date:** March 28, 2019 * **Source added by :** Steve King **Date:** March 25, 2019 single = False have_Fq = True effective_radius_type = ["outer radius"] radius_effective_modes = ["outer radius"] profile_axes = ['Radius (A)', 'SLD (1e-6/A^2)']
• ## sasmodels/models/parallelepiped.c

 r99658f6 static double effective_radius(int mode, double length_a, double length_b, double length_c) radius_effective(int mode, double length_a, double length_b, double length_c) { switch (mode) {
• ## sasmodels/models/parallelepiped.py

 r0507e09 source = ["lib/gauss76.c", "parallelepiped.c"] have_Fq = True effective_radius_type = [ radius_effective_modes = [ "equivalent cylinder excluded volume", "equivalent volume sphere", "half length_a", "half length_b", "half length_c",
• ## sasmodels/models/pearl_necklace.c

 r9b5fd42 static double effective_radius(int mode, double radius, double edge_sep, double thick_string, double fp_num_pearls) radius_effective(int mode, double radius, double edge_sep, double thick_string, double fp_num_pearls) { switch (mode) {
• ## sasmodels/models/pearl_necklace.py

 rc0136c72 source = ["lib/sas_Si.c", "lib/sas_3j1x_x.c", "pearl_necklace.c"] single = False  # use double precision unless told otherwise effective_radius_type = ["equivalent volume sphere"] radius_effective_modes = ["equivalent volume sphere"] def random():
• ## sasmodels/models/poly_gauss_coil.py

 r0507e09 ---------------------------- * **Author:** * **Last Modified by:** * **Last Reviewed by:** * **Author:** * **Last Modified by:** * **Last Reviewed by:** * **Source added by :** Steve King **Date:** March 25, 2019 """
• ## sasmodels/models/pringle.c

 r99658f6 static double effective_radius(int mode, double radius, double thickness, double alpha, double beta) radius_effective(int mode, double radius, double thickness, double alpha, double beta) { switch (mode) {
• ## sasmodels/models/pringle.py

 r0507e09 source = ["lib/polevl.c", "lib/sas_J0.c", "lib/sas_J1.c", "lib/sas_JN.c", "lib/gauss76.c", "pringle.c"] effective_radius_type = [ radius_effective_modes = [ "equivalent cylinder excluded volume", "equivalent volume sphere",

• ## sasmodels/models/rectangular_prism.c

 r99658f6 static double effective_radius(int mode, double length_a, double b2a_ratio, double c2a_ratio) radius_effective(int mode, double length_a, double b2a_ratio, double c2a_ratio) { switch (mode) {
• ## sasmodels/models/rectangular_prism.py

 r0507e09 ---------------------------- * **Author:** * **Last Modified by:** * **Last Reviewed by:** * **Author:** * **Last Modified by:** * **Last Reviewed by:** * **Source added by :** Steve King **Date:** March 25, 2019 """ source = ["lib/gauss76.c", "rectangular_prism.c"] have_Fq = True effective_radius_type = [ radius_effective_modes = [ "equivalent cylinder excluded volume", "equivalent volume sphere", "half length_a", "half length_b", "half length_c",
• ## sasmodels/models/rpa.py

 r055ec4f that $R_g^2 = n b^2/6$ where $b$ is the statistical segment length and $n$ is the number of statistical segment lengths. A nice tutorial on how these are constructed and implemented can be found in chapters 28, 31 and 34, and Part H, constructed and implemented can be found in chapters 28, 31 and 34, and Part H, of Hammouda's 'SANS Toolbox' [3].

• ## sasmodels/models/spherical_sld.c

 ree60aa7 static double effective_radius(int mode, double fp_n_shells, double thickness[], double interface[]) radius_effective(int mode, double fp_n_shells, double thickness[], double interface[]) { // case 1: outer radius
• ## sasmodels/models/spherical_sld.py

 r0507e09 sub-shell is described by a line function, with *n_steps* sub-shells per interface. The form factor is normalized by the total volume of the sphere. .. note:: *n_shells* must be an integer. *n_steps* must be an ODD integer. Interface shapes are as follows: 3 \rho_\text{solvent} V(r_N) \Big[ \frac{\sin(qr_N) - qr_N \cos(qr_N)} {qr_N^3} \Big] Here we assumed that the SLDs of the core and solvent are constant in $r$. \end{align*} We assume $\rho_{\text{inter}_j} (r)$ is approximately linear within the sub-shell $j$. when $P(Q) * S(Q)$ is applied. References ---------- Authorship and Verification ---------------------------- --------------------------- * **Author:** Jae-Hie Cho **Date:** Nov 1, 2010 * **Last Modified by:** Paul Kienzle **Date:** Dec 20, 2016 * **Last Reviewed by:** Paul Butler **Date:** September 8, 2018 * **Last Reviewed by:** Steve King **Date:** March 29, 2019 * **Source added by :** Steve King **Date:** March 25, 2019 """ name = "spherical_sld" title = "Sperical SLD intensity calculation" title = "Spherical SLD intensity calculation" description = """ I(q) = # pylint: disable=bad-whitespace, line-too-long #            ["name", "units", default, [lower, upper], "type", "description"], parameters = [["n_shells",             "",           1,      [1, 10],        "volume", "number of shells"], parameters = [["n_shells",             "",           1,      [1, 10],        "volume", "number of shells (must be integer)"], ["sld_solvent",          "1e-6/Ang^2", 1.0,    [-inf, inf],    "sld", "solvent sld"], ["sld[n_shells]",        "1e-6/Ang^2", 4.06,   [-inf, inf],    "sld", "sld of the shell"], single = False  # TODO: fix low q behaviour have_Fq = True effective_radius_type = ["outer radius"] radius_effective_modes = ["outer radius"] profile_axes = ['Radius (A)', 'SLD (1e-6/A^2)']
• ## sasmodels/models/squarewell.py

 r5f3c534 # Note: model title and parameter table are inserted automatically r""" Calculates the interparticle structure factor for a hard sphere fluid with a narrow, attractive, square well potential. **The Mean Spherical Approximation (MSA) closure relationship is used, but it is not the most appropriate closure for an attractive interparticle potential.** However, the solution has been compared to Monte Carlo simulations for a square well fluid and these show the MSA calculation to be limited to well Calculates the interparticle structure factor for a hard sphere fluid with a narrow, attractive, square well potential. **The Mean Spherical Approximation (MSA) closure relationship is used, but it is not the most appropriate closure for an attractive interparticle potential.** However, the solution has been compared to Monte Carlo simulations for a square well fluid and these show the MSA calculation to be limited to well depths $\epsilon < 1.5$ kT and volume fractions $\phi < 0.08$. Positive well depths correspond to an attractive potential well. Negative well depths correspond to a potential "shoulder", which may or may not be physically reasonable. The :ref:stickyhardsphere model may be a better physically reasonable. The :ref:stickyhardsphere model may be a better choice in some circumstances. .. note:: Earlier versions of SasView did not incorporate the so-called $\beta(q)$ ("beta") correction [2] for polydispersity and non-sphericity. Earlier versions of SasView did not incorporate the so-called $\beta(q)$ ("beta") correction [2] for polydispersity and non-sphericity. This is only available in SasView versions 4.2.2 and higher. ---------------------------- * **Author:** * **Last Modified by:** * **Author:** * **Last Modified by:** * **Last Reviewed by:** Steve King **Date:** March 27, 2019 * **Source added by :** Steve King **Date:** March 25, 2019 description = """\ [Square well structure factor, with MSA closure] Interparticle structure factor S(Q) for a hard sphere fluid Interparticle structure factor S(Q) for a hard sphere fluid with a narrow attractive well. Fits are prone to deliver non- physical parameters; use with care and read the references in the model documentation.The "beta(q)" correction is available physical parameters; use with care and read the references in the model documentation.The "beta(q)" correction is available in versions 4.2.2 and higher. """
• ## sasmodels/models/stickyhardsphere.py

 r5f3c534 # Note: model title and parameter table are inserted automatically r""" Calculates the interparticle structure factor for a hard sphere fluid with a narrow, attractive, potential well. Unlike the :ref:squarewell model, here a perturbative solution of the Percus-Yevick closure relationship is used. The strength of the attractive well is described Calculates the interparticle structure factor for a hard sphere fluid with a narrow, attractive, potential well. Unlike the :ref:squarewell model, here a perturbative solution of the Percus-Yevick closure relationship is used. The strength of the attractive well is described in terms of "stickiness" as defined below. The perturbation parameter (perturb), $\tau$, should be fixed between 0.01 and 0.1 and the "stickiness", $\epsilon$, allowed to vary to adjust the interaction strength. The "stickiness" is defined in the equation below and is a function of both the perturbation parameter and the interaction strength. $\epsilon$ and $\tau$ are defined in terms of the hard sphere diameter $(\sigma = 2 R)$, the width of the square well, $\Delta$ (having the same units as $R$\ ), and the depth of the well, $U_o$, in units of $kT$. From the definition, it and 0.1 and the "stickiness", $\epsilon$, allowed to vary to adjust the interaction strength. The "stickiness" is defined in the equation below and is a function of both the perturbation parameter and the interaction strength. $\epsilon$ and $\tau$ are defined in terms of the hard sphere diameter $(\sigma = 2 R)$, the width of the square well, $\Delta$ (having the same units as $R$\ ), and the depth of the well, $U_o$, in units of $kT$. From the definition, it is clear that smaller $\epsilon$ means a stronger attraction. The true particle volume fraction, $\phi$, is not equal to $h$ which appears in most of reference [1]. The two are related in equation (24). Reference [1] also describes the relationship between this perturbative solution and in most of reference [1]. The two are related in equation (24). Reference [1] also describes the relationship between this perturbative solution and the original sticky hard sphere (or "adhesive sphere") model of Baxter [2]. reported to the command window and $S(q)$ is set to -1 (so it will disappear on a log-log plot!). Use tight bounds to keep the parameters to values that you know are physical (test them), and keep nudging them until the optimization Use tight bounds to keep the parameters to values that you know are physical (test them), and keep nudging them until the optimization does not hit the constraints. .. note:: Earlier versions of SasView did not incorporate the so-called $\beta(q)$ ("beta") correction [3] for polydispersity and non-sphericity. Earlier versions of SasView did not incorporate the so-called $\beta(q)$ ("beta") correction [3] for polydispersity and non-sphericity. This is only available in SasView versions 4.2.2 and higher. In SasView the effective radius may be calculated from the parameters used in the form factor $P(q)$ that this $S(q)$ is combined with. ---------------------------- * **Author:** * **Last Modified by:** * **Author:** * **Last Modified by:** * **Last Reviewed by:** Steve King **Date:** March 27, 2019 * **Source added by :** Steve King **Date:** March 25, 2019 description = """\ [Sticky hard sphere structure factor, with Percus-Yevick closure] Interparticle structure factor S(Q) for a hard sphere fluid Interparticle structure factor S(Q) for a hard sphere fluid with a narrow attractive well. Fits are prone to deliver non- physical parameters; use with care and read the references in the model documentation.The "beta(q)" correction is available physical parameters; use with care and read the references in the model documentation.The "beta(q)" correction is available in versions 4.2.2 and higher. """

• ## sasmodels/models/triaxial_ellipsoid.py

 r0507e09 source = ["lib/sas_3j1x_x.c", "lib/gauss76.c", "triaxial_ellipsoid.c"] have_Fq = True effective_radius_type = [ radius_effective_modes = [ "equivalent biaxial ellipsoid average curvature", "equivalent volume sphere", "min radius", "max radius",
• ## sasmodels/models/unified_power_Rg.py

 r7a5f8af ------ unified_power_rg.py _ unified_power_Rg.py _ Authorship and Verification category = "shape-independent" name = "unified_power_rg" name = "unified_power_Rg" title = "Unified Power Rg" description = """