source: sasmodels/sasmodels/models/hayter_msa.py @ c1e44e5

Last change on this file since c1e44e5 was c1e44e5, checked in by Paul Kienzle <pkienzle@…>, 5 years ago

Add local link to source files. Refs #1263.

  • Property mode set to 100644
File size: 6.9 KB
Line 
1# Note: model title and parameter table are inserted automatically
2r"""
3Calculates the interparticle structure factor for a system of charged,
4spheroidal, objects in a dielectric medium [1,2]. When combined with an
5appropriate form factor $P(q)$, this allows for inclusion of the
6interparticle interference effects due to screened Coulombic
7repulsion between the charged particles.
8
9.. note::
10
11   This routine only works for charged particles! If the charge is set
12   to zero the routine may self-destruct! For uncharged particles use
13   the :ref:`hardsphere` $S(q)$ instead. The upper limit for the charge
14   is limited to 200e to avoid numerical instabilities.
15
16.. note::
17
18   Earlier versions of SasView did not incorporate the so-called
19   $\beta(q)$ ("beta") correction [3] for polydispersity and non-sphericity.
20   This is only available in SasView versions 4.2.2 and higher.
21
22The salt concentration is used to compute the ionic strength of the solution
23which in turn is used to compute the Debye screening length. There is no
24provision for entering the ionic strength directly. **At present the
25counterions are assumed to be monovalent**, though it should be possible
26to simulate the effect of multivalent counterions by increasing the salt
27concentration.
28
29Over the range 0 - 100 C the dielectric constant $\kappa$ of water may be
30approximated with a maximum deviation of 0.01 units by the empirical
31formula [4]
32
33.. math::
34
35    \kappa = 87.740 - 0.40008 T + 9.398x10^{-4} T^2 - 1.410x10^{-6} T^3
36
37where $T$ is the temperature in celsius.
38
39In SasView the effective radius may be calculated from the parameters
40used in the form factor $P(q)$ that this $S(q)$ is combined with.
41
42The computation uses a Taylor series expansion at very small rescaled $qR$, to
43avoid some serious rounding error issues, this may result in a minor artefact
44in the transition region under some circumstances.
45
46For 2D data, the scattering intensity is calculated in the same way as 1D,
47where the $q$ vector is defined as
48
49.. math::
50
51    q = \sqrt{q_x^2 + q_y^2}
52
53
54References
55----------
56
57.. [#] J B Hayter and J Penfold, *Molecular Physics*, 42 (1981) 109-118
58
59.. [#] J P Hansen and J B Hayter, *Molecular Physics*, 46 (1982) 651-656
60
61.. [#] M Kotlarchyk and S-H Chen, *J. Chem. Phys.*, 79 (1983) 2461-2469
62
63.. [#] C G Malmberg and A A Maryott, *J. Res. Nat. Bureau Standards*, 56 (1956) 2641
64
65Authorship and Verification
66----------------------------
67
68* **Author:**
69* **Last Modified by:**
70* **Last Reviewed by:** Steve King **Date:** March 28, 2019
71"""
72
73import numpy as np
74from numpy import inf
75
76category = "structure-factor"
77structure_factor = True
78single = False  # double precision only!
79
80#  dp[0] = 2.0*radius_effective();
81#  dp[1] = fabs(charge());
82#  dp[2] = volfraction();
83#  dp[3] = temperature();
84#  dp[4] = concentration_salt();
85#  dp[5] = dielectconst();
86
87
88
89
90name = "hayter_msa"
91title = "Hayter-Penfold Rescaled Mean Spherical Approximation (RMSA) structure factor for charged spheres"
92description = """\
93    [Hayter-Penfold RMSA charged sphere interparticle S(Q) structure factor]
94        Interparticle structure factor S(Q) for charged hard spheres.
95    This routine only works for charged particles! For uncharged particles
96    use the hardsphere S(q) instead. The "beta(q)" correction is available
97    in versions 4.2.2 and higher.
98"""
99
100
101# pylint: disable=bad-whitespace, line-too-long
102#             [ "name", "units", default, [lower, upper], "type", "description" ],
103#
104# NOTE: SMK, 28Mar19 The upper limit for charge is set to 200 to avoid instabilities noted by PK in
105#       Ticket #1152. Also see the thread in Ticket 859. The docs above also note that charge=0 will
106#       cause problems, yet the default parameters allowed it! After discussions with PK I have
107#       changed it to (an arbitarily) small but non-zero value.  But I haven't changed the low limit
108#       in function random() below.
109#
110parameters = [
111    ["radius_effective", "Ang", 20.75,   [0, inf],    "volume", "effective radius of charged sphere"],
112    ["volfraction",   "None",     0.0192, [0, 0.74],   "", "volume fraction of spheres"],
113    ["charge",        "e",   19.0,    [0.000001, 200],    "", "charge on sphere (in electrons)"],
114    ["temperature",   "K",  318.16,   [0, 450],    "", "temperature, in Kelvin, for Debye length calculation"],
115    ["concentration_salt",      "M",    0.0,    [0, inf], "", "conc of salt, moles/litre, 1:1 electolyte, for Debye length"],
116    ["dielectconst",  "None",    71.08,   [-inf, inf], "", "dielectric constant (relative permittivity) of solvent, kappa, default water, for Debye length"]
117    ]
118# pylint: enable=bad-whitespace, line-too-long
119
120source = ["hayter_msa.c"]
121# No volume normalization despite having a volume parameter
122# This should perhaps be volume normalized?
123form_volume = """
124    return 1.0;
125    """
126
127def random():
128    """Return a random parameter set for the model."""
129    # TODO: too many failures for random hayter_msa parameters
130    pars = dict(
131        scale=1, background=0,
132        radius_effective=10**np.random.uniform(1, 4.7),
133        volfraction=10**np.random.uniform(-2, 0),  # high volume fraction
134        charge=min(int(10**np.random.uniform(0, 1.3)+0.5), 200),
135        temperature=10**np.random.uniform(0, np.log10(450)), # max T = 450
136        #concentration_salt=10**np.random.uniform(-3, 1),
137        dialectconst=10**np.random.uniform(0, 6),
138        #charge=10,
139        #temperature=318.16,
140        concentration_salt=0.0,
141        #dielectconst=71.08,
142    )
143    return pars
144
145# default parameter set,  use  compare.sh -midQ -linear
146# note the calculation varies in different limiting cases so a wide range of
147# parameters will be required for a thorough test!
148# odd that the default st has concentration_salt zero
149demo = dict(radius_effective=20.75,
150            charge=19.0,
151            volfraction=0.0192,
152            temperature=318.16,
153            concentration_salt=0.05,
154            dielectconst=71.08,
155            radius_effective_pd=0.1,
156            radius_effective_pd_n=40)
157#
158# attempt to use same values as old sasview unit test at Q=.001 was 0.0712928,
159# then add lots new ones assuming values from new model are OK, need some
160# low Q values to test the small Q Taylor expansion
161tests = [
162    [{'scale': 1.0,
163      'background': 0.0,
164      'radius_effective': 20.75,
165      'charge': 19.0,
166      'volfraction': 0.0192,
167      'temperature': 298.0,
168      'concentration_salt': 0,
169      'dielectconst': 78.0,
170      'radius_effective_pd': 0},
171     [0.00001, 0.0010, 0.01, 0.075], [0.0711646, 0.0712928, 0.0847006, 1.07150]],
172    [{'scale': 1.0,
173      'background': 0.0,
174      'radius_effective': 20.75,
175      'charge': 19.0,
176      'volfraction': 0.0192,
177      'temperature': 298.0,
178      'concentration_salt': 0.05,
179      'dielectconst': 78.0,
180      'radius_effective_pd': 0.1,
181      'radius_effective_pd_n': 40},
182     [0.00001, 0.0010, 0.01, 0.075], [0.450272, 0.450420, 0.465116, 1.039625]]
183    ]
184# ADDED by:  RKH  ON: 16Mar2016 converted from sasview, new Taylor expansion at smallest rescaled Q
Note: See TracBrowser for help on using the repository browser.