File: gauss_lorentz_gel.py

package info (click to toggle)
mccode 3.5.19%2Bds5-2
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 1,113,256 kB
  • sloc: ansic: 40,697; python: 25,137; yacc: 8,438; sh: 5,405; javascript: 4,596; lex: 1,632; cpp: 742; perl: 296; lisp: 273; makefile: 226; fortran: 132
file content (155 lines) | stat: -rw-r--r-- 5,097 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
r"""
This model calculates the scattering from a gel structure,
but typically a physical rather than chemical network.
It is modeled as a sum of a low-q exponential decay (which happens to
give a functional form similar to Guinier scattering, so interpret with
care) plus a Lorentzian at higher-q values. See also the gel_fit model.

Definition
----------

The scattering intensity $I(q)$ is calculated as (Eqn. 5 from the reference)

.. math:: I(q) = I_G(0) \exp(-q^2\Xi ^2/2) + I_L(0)/(1+q^2\xi^2)

$\Xi$ is the length scale of the static correlations in the gel, which can
be attributed to the "frozen-in" crosslinks. $\xi$ is the dynamic correlation
length, which can be attributed to the fluctuating polymer chains between
crosslinks. $I_G(0)$ and $I_L(0)$ are the scaling factors for each of these
structures. Think carefully about how these map to your particular system!

.. note::
    The peaked structure at higher $q$ values (Figure 2 from the reference)
    is not reproduced by the model. Peaks can be introduced into the model
    by summing this model with the :ref:`gaussian-peak` model.

For 2D data the scattering intensity is calculated in the same way as 1D,
where the $q$ vector is defined as

.. math:: q = \sqrt{q_x^2 + q_y^2}

References
----------

#. G Evmenenko, E Theunissen, K Mortensen, H Reynaers,
   *Polymer*, 42 (2001) 2907-2913

Authorship and Verification
----------------------------

* **Author:**
* **Last Modified by:**
* **Last Reviewed by:**
"""

import numpy as np
from numpy import inf, exp

name = "gauss_lorentz_gel"
title = "Gauss Lorentz Gel model of scattering from a gel structure"
description = """
            Class that evaluates a GaussLorentzGel model.

            I(q) = scale_g*exp(- q^2*Z^2 / 2)+scale_l/(1+q^2*z^2)
                    + background
            List of default parameters:
                scale_g = Gauss scale factor
                Z = Static correlation length
                scale_l = Lorentzian scale factor
                z = Dynamic correlation length
                background = Incoherent background
            """
category = "shape-independent"
# pylint: disable=bad-whitespace, line-too-long
#            ["name", "units", default, [lower, upper], "type", "description"],
parameters = [["gauss_scale",   "",    100.0,  [-inf, inf], "", "Gauss scale factor"],
              ["cor_length_static",    "Ang", 100.0,  [0, inf],    "", "Static correlation length"],
              ["lorentz_scale", "",     50.0,  [-inf, inf], "", "Lorentzian scale factor"],
              ["cor_length_dynamic",   "Ang",  20.0,  [0, inf],    "", "Dynamic correlation length"],
             ]
# pylint: enable=bad-whitespace, line-too-long

def Iq(q,
       gauss_scale=100.0,
       cor_length_static=100.0,
       lorentz_scale=50.0,
       cor_length_dynamic=20.0):
    """

    :param q:                    Input q-value
    :param gauss_scale:   Gauss scale factor
    :param cor_length_static:    Static correlation length
    :param lorentz_scale: Lorentzian scale factor
    :param cor_length_dynamic:   Dynamic correlation length
    :return:                     1-D intensity
    """

    term1 = gauss_scale *\
            exp(-1.0*q*q*cor_length_static*cor_length_static/2.0)
    term2 = lorentz_scale /\
            (1.0+(q*cor_length_dynamic)*(q*cor_length_dynamic))

    return term1 + term2

Iq.vectorized = True  # Iq accepts an array of q values


def random():
    """Return a random parameter set for the model."""
    gauss_scale = 10**np.random.uniform(1, 3)
    lorentz_scale = 10**np.random.uniform(1, 3)
    cor_length_static = 10**np.random.uniform(0, 3)
    cor_length_dynamic = 10**np.random.uniform(0, 3)
    pars = dict(
        #background=0,
        scale=1,
        gauss_scale=gauss_scale,
        lorentz_scale=lorentz_scale,
        cor_length_static=cor_length_static,
        cor_length_dynamic=cor_length_dynamic,
    )
    return pars


tests = [

    # Accuracy tests based on content in test/utest_extra_models.py
    [{'gauss_scale':  100.0,
      'cor_length_static':   100.0,
      'lorentz_scale': 50.0,
      'cor_length_dynamic':   20.0,
     }, 0.001, 149.482],

    [{'gauss_scale':  100.0,
      'cor_length_static':   100.0,
      'lorentz_scale': 50.0,
      'cor_length_dynamic':   20.0,
     }, 0.105363, 9.1913],

    [{'gauss_scale':  100.0,
      'cor_length_static':   100.0,
      'lorentz_scale': 50.0,
      'cor_length_dynamic':   20.0,
     }, 0.441623, 0.633811],

    # Additional tests with larger range of parameters
    [{'gauss_scale':  10.0,
      'cor_length_static':  100.0,
      'lorentz_scale': 3.0,
      'cor_length_dynamic':   1.0,
     }, 0.1, 2.9712970297],

    [{'gauss_scale':  10.0,
      'cor_length_static':  100.0,
      'lorentz_scale': 3.0,
      'cor_length_dynamic':   1.0,
      'background':         100.0
     }, 5.0, 100.116384615],

    [{'gauss_scale':  10.0,
      'cor_length_static':  100.0,
      'lorentz_scale': 3.0,
      'cor_length_dynamic':   1.0,
      'background':           0.0,
     }, 200., 7.49981250469e-05],
    ]