source: sasmodels/sasmodels/models/guinier_porod.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: 4.4 KB
Line 
1r"""
2Calculates the scattering for a generalized Guinier/power law object.
3This is an empirical model that can be used to determine the size
4and dimensionality of scattering objects, including asymmetric objects
5such as rods or platelets, and shapes intermediate between spheres
6and rods or between rods and platelets, and overcomes some of the
7deficiencies of the (Beaucage) :ref:`unified-power-rg` model (see Hammouda, 2010).
8
9Definition
10----------
11
12The following functional form is used
13
14.. math::
15
16    I(q) = \begin{cases}
17    \frac{G}{Q^s}\ \exp{\left[\frac{-Q^2R_g^2}{3-s} \right]} & Q \leq Q_1 \\
18    D / Q^m  & Q \geq Q_1
19    \end{cases}
20
21This is based on the generalized Guinier law for such elongated objects
22(see the Glatter reference below). For 3D globular objects (such as spheres),
23$s = 0$ and one recovers the standard Guinier formula. For 2D symmetry
24(such as for rods) $s = 1$, and for 1D symmetry (such as for lamellae or
25platelets) $s = 2$. A dimensionality parameter ($3-s$) is thus defined,
26and is 3 for spherical objects, 2 for rods, and 1 for plates.
27
28Enforcing the continuity of the Guinier and Porod functions and their
29derivatives yields
30
31.. math::
32
33    Q_1 = \frac{1}{R_g} \sqrt{(m-s)(3-s)/2}
34
35and
36
37.. math::
38
39    D &= G \ \exp{ \left[ \frac{-Q_1^2 R_g^2}{3-s} \right]} \ Q_1^{m-s}
40
41      &= \frac{G}{R_g^{m-s}} \ \exp \left[ -\frac{m-s}{2} \right]
42          \left( \frac{(m-s)(3-s)}{2} \right)^{\frac{m-s}{2}}
43
44
45Note that the radius of gyration for a sphere of radius $R$ is given
46by $R_g = R \sqrt{3/5}$. For a cylinder of radius $R$ and length $L$,
47$R_g^2 = \frac{L^2}{12} + \frac{R^2}{2}$ from which the cross-sectional
48radius of gyration for a randomly oriented thin cylinder is $R_g = R/\sqrt{2}$
49and the cross-sectional radius of gyration of a randomly oriented lamella
50of thickness $T$ is given by $R_g = T / \sqrt{12}$.
51
52For 2D data: The 2D scattering intensity is calculated in the same way as 1D,
53where the q vector is defined as
54
55.. math::
56    q = \sqrt{q_x^2+q_y^2}
57
58
59Reference
60---------
61
62.. [#] B Hammouda, *A new Guinier-Porod model, J. Appl. Cryst.*, (2010), 43, 716-719
63.. [#] B Hammouda, *Analysis of the Beaucage model, J. Appl. Cryst.*, (2010), 43, 1474-1478
64
65Authorship and Verification
66----------------------------
67
68* **Author:**
69* **Last Modified by:**
70* **Last Reviewed by:**
71"""
72
73import numpy as np
74from numpy import inf, sqrt, exp, errstate
75
76name = "guinier_porod"
77title = "Guinier-Porod function"
78description = """\
79         I(q) = scale/q^s* exp ( - R_g^2 q^2 / (3-s) ) for q<= ql
80         = scale/q^porod_exp*exp((-ql^2*Rg^2)/(3-s))*ql^(porod_exp-s) for q>=ql
81                        where ql = sqrt((porod_exp-s)(3-s)/2)/Rg.
82                        List of parameters:
83                        scale = Guinier Scale
84                        s = Dimension Variable
85                        Rg = Radius of Gyration [A]
86                        porod_exp = Porod Exponent
87                        background  = Background [1/cm]"""
88
89category = "shape-independent"
90
91# pylint: disable=bad-whitespace, line-too-long
92#             ["name", "units", default, [lower, upper], "type","description"],
93parameters = [["rg", "Ang", 60.0, [0, inf], "", "Radius of gyration"],
94              ["s",  "",    1.0,  [0, inf], "", "Dimension variable"],
95              ["porod_exp",  "",    3.0,  [0, inf], "", "Porod exponent"]]
96# pylint: enable=bad-whitespace, line-too-long
97
98# pylint: disable=C0103
99def Iq(q, rg, s, porod_exp):
100    """
101    @param q: Input q-value
102    """
103    n = 3.0 - s
104    ms = 0.5*(porod_exp-s) # =(n-3+porod_exp)/2
105
106    # preallocate return value
107    iq = 0.0*q
108
109    # Take care of the singular points
110    if rg <= 0.0 or ms <= 0.0:
111        return iq
112
113    # Do the calculation and return the function value
114    idx = q < sqrt(n*ms)/rg
115    with errstate(divide='ignore'):
116        iq[idx] = q[idx]**-s * exp(-(q[idx]*rg)**2/n)
117        iq[~idx] = q[~idx]**-porod_exp * (exp(-ms) * (n*ms/rg**2)**ms)
118    return iq
119
120Iq.vectorized = True # Iq accepts an array of q values
121
122def random():
123    """Return a random parameter set for the model."""
124    rg = 10**np.random.uniform(1, 5)
125    s = np.random.uniform(0, 3)
126    porod_exp = s + np.random.uniform(0, 3)
127    pars = dict(
128        #scale=1, background=0,
129        rg=rg,
130        s=s,
131        porod_exp=porod_exp,
132    )
133    return pars
134
135demo = dict(scale=1.5, background=0.5, rg=60, s=1.0, porod_exp=3.0)
136
137tests = [[{'scale': 1.5, 'background':0.5}, 0.04, 5.290096890253155]]
Note: See TracBrowser for help on using the repository browser.