source: sasmodels/sasmodels/models/core_shell_parallelepiped.py @ 0e55afe

core_shell_microgelsmagnetic_modelticket-1257-vesicle-productticket_1156ticket_1265_superballticket_822_more_unit_tests
Last change on this file since 0e55afe was 0e55afe, checked in by Paul Kienzle <pkienzle@…>, 6 years ago

Merge branch 'master' into ticket-786

  • Property mode set to 100644
File size: 9.1 KB
Line 
1r"""
2Definition
3----------
4
5Calculates the form factor for a rectangular solid with a core-shell structure.
6The thickness and the scattering length density of the shell or
7"rim" can be different on each (pair) of faces.
8
9The form factor is normalized by the particle volume $V$ such that
10
11.. math::
12
13    I(q) = \text{scale}\frac{\langle f^2 \rangle}{V} + \text{background}
14
15where $\langle \ldots \rangle$ is an average over all possible orientations
16of the rectangular solid.
17
18The function calculated is the form factor of the rectangular solid below.
19The core of the solid is defined by the dimensions $A$, $B$, $C$ such that
20$A < B < C$.
21
22.. image:: img/core_shell_parallelepiped_geometry.jpg
23
24There are rectangular "slabs" of thickness $t_A$ that add to the $A$ dimension
25(on the $BC$ faces). There are similar slabs on the $AC$ $(=t_B)$ and $AB$
26$(=t_C)$ faces. The projection in the $AB$ plane is then
27
28.. image:: img/core_shell_parallelepiped_projection.jpg
29
30The volume of the solid is
31
32.. math::
33
34    V = ABC + 2t_ABC + 2t_BAC + 2t_CAB
35
36**meaning that there are "gaps" at the corners of the solid.**
37
38The intensity calculated follows the :ref:`parallelepiped` model, with the
39core-shell intensity being calculated as the square of the sum of the
40amplitudes of the core and the slabs on the edges.
41
42the scattering amplitude is computed for a particular orientation of the core-shell
43parallelepiped with respect to the scattering vector and then averaged over all
44possible orientations, where $\alpha$ is the angle between the $z$ axis and the longest axis $C$
45of the parallelepiped, $\beta$ is the angle between projection of the particle in the $xy$ detector plane and the $y$ axis.
46
47.. math::
48    \begin{align*}
49    F(Q)&=A B C (\rho_\text{core}-\rho_\text{solvent})  S(A \sin\alpha \sin\beta)S(B \sin\alpha \cos\beta)S(C \cos\alpha) \\
50    &+ 2t_A B C (\rho_\text{A}-\rho_\text{solvent})  \left[S((A+t_A) \sin\alpha \sin\beta)-S(A \sin\alpha \sin\beta)\right] S(B \sin\alpha \cos\beta) S(C \cos\alpha)\\
51    &+ 2 A t_B C (\rho_\text{B}-\rho_\text{solvent})  S(A \sin\alpha \sin\beta) \left[S((B+t_B) \sin\alpha \cos\beta)-S(B \sin\alpha \cos\beta)\right] S(C \cos\alpha)\\
52    &+ 2 A B t_C (\rho_\text{C}-\rho_\text{solvent}) S(A \sin\alpha \sin\beta) S(B \sin\alpha \cos\beta) \left[S((C+t_C) \cos\alpha)-S(C \cos\alpha)\right]
53    \end{align*}
54
55with
56
57.. math::
58
59    S(x) = \frac{\sin \tfrac{1}{2}Q x}{\tfrac{1}{2}Q x}
60
61where $\rho_\text{core}$, $\rho_\text{A}$, $\rho_\text{B}$ and $\rho_\text{C}$ are
62the scattering length of the parallelepiped core, and the rectangular slabs of
63thickness $t_A$, $t_B$ and $t_C$, respectively.
64$\rho_\text{solvent}$ is the scattering length of the solvent.
65
66FITTING NOTES
67If the scale is set equal to the particle volume fraction, $\phi$, the returned
68value is the scattered intensity per unit volume, $I(q) = \phi P(q)$.
69However, **no interparticle interference effects are included in this
70calculation.**
71
72There are many parameters in this model. Hold as many fixed as possible with
73known values, or you will certainly end up at a solution that is unphysical.
74
75The returned value is in units of |cm^-1|, on absolute scale.
76
77NB: The 2nd virial coefficient of the core_shell_parallelepiped is calculated
78based on the the averaged effective radius $(=\sqrt{(A+2t_A)(B+2t_B)/\pi})$
79and length $(C+2t_C)$ values, after appropriately
80sorting the three dimensions to give an oblate or prolate particle, to give an
81effective radius, for $S(Q)$ when $P(Q) * S(Q)$ is applied.
82
83For 2d data the orientation of the particle is required, described using
84angles $\theta$, $\phi$ and $\Psi$ as in the diagrams below, for further details
85of the calculation and angular dispersions see :ref:`orientation` .
86The angle $\Psi$ is the rotational angle around the *long_c* axis. For example,
87$\Psi = 0$ when the *short_b* axis is parallel to the *x*-axis of the detector.
88
89For 2d, constraints must be applied during fitting to ensure that the inequality
90$A < B < C$ is not violated, and hence the correct definition of angles is preserved. The calculation will not report an error,
91but the results may be not correct.
92
93.. figure:: img/parallelepiped_angle_definition.png
94
95    Definition of the angles for oriented core-shell parallelepipeds.
96    Note that rotation $\theta$, initially in the $xz$ plane, is carried
97    out first, then rotation $\phi$ about the $z$ axis, finally rotation
98    $\Psi$ is now around the axis of the cylinder. The neutron or X-ray
99    beam is along the $z$ axis.
100
101.. figure:: img/parallelepiped_angle_projection.png
102
103    Examples of the angles for oriented core-shell parallelepipeds against the
104    detector plane.
105
106References
107----------
108
109.. [#] P Mittelbach and G Porod, *Acta Physica Austriaca*, 14 (1961) 185-211
110    Equations (1), (13-14). (in German)
111.. [#] D Singh (2009). *Small angle scattering studies of self assembly in
112   lipid mixtures*, Johns Hopkins University Thesis (2009) 223-225. `Available
113   from Proquest <http://search.proquest.com/docview/304915826?accountid
114   =26379>`_
115
116Authorship and Verification
117----------------------------
118
119* **Author:** NIST IGOR/DANSE **Date:** pre 2010
120* **Converted to sasmodels by:** Miguel Gonzales **Date:** February 26, 2016
121* **Last Modified by:** Wojciech Potrzebowski **Date:** January 11, 2017
122* **Currently Under review by:** Paul Butler
123"""
124
125import numpy as np
126from numpy import pi, inf, sqrt, cos, sin
127
128name = "core_shell_parallelepiped"
129title = "Rectangular solid with a core-shell structure."
130description = """
131     P(q)=
132"""
133category = "shape:parallelepiped"
134
135#             ["name", "units", default, [lower, upper], "type","description"],
136parameters = [["sld_core", "1e-6/Ang^2", 1, [-inf, inf], "sld",
137               "Parallelepiped core scattering length density"],
138              ["sld_a", "1e-6/Ang^2", 2, [-inf, inf], "sld",
139               "Parallelepiped A rim scattering length density"],
140              ["sld_b", "1e-6/Ang^2", 4, [-inf, inf], "sld",
141               "Parallelepiped B rim scattering length density"],
142              ["sld_c", "1e-6/Ang^2", 2, [-inf, inf], "sld",
143               "Parallelepiped C rim scattering length density"],
144              ["sld_solvent", "1e-6/Ang^2", 6, [-inf, inf], "sld",
145               "Solvent scattering length density"],
146              ["length_a", "Ang", 35, [0, inf], "volume",
147               "Shorter side of the parallelepiped"],
148              ["length_b", "Ang", 75, [0, inf], "volume",
149               "Second side of the parallelepiped"],
150              ["length_c", "Ang", 400, [0, inf], "volume",
151               "Larger side of the parallelepiped"],
152              ["thick_rim_a", "Ang", 10, [0, inf], "volume",
153               "Thickness of A rim"],
154              ["thick_rim_b", "Ang", 10, [0, inf], "volume",
155               "Thickness of B rim"],
156              ["thick_rim_c", "Ang", 10, [0, inf], "volume",
157               "Thickness of C rim"],
158              ["theta", "degrees", 0, [-360, 360], "orientation",
159               "c axis to beam angle"],
160              ["phi", "degrees", 0, [-360, 360], "orientation",
161               "rotation about beam"],
162              ["psi", "degrees", 0, [-360, 360], "orientation",
163               "rotation about c axis"],
164             ]
165
166source = ["lib/gauss76.c", "core_shell_parallelepiped.c"]
167
168
169def ER(length_a, length_b, length_c, thick_rim_a, thick_rim_b, thick_rim_c):
170    """
171        Return equivalent radius (ER)
172    """
173
174    # surface average radius (rough approximation)
175    surf_rad = sqrt((length_a + 2.0*thick_rim_a) * (length_b + 2.0*thick_rim_b) / pi)
176
177    height = length_c + 2.0*thick_rim_c
178
179    ddd = 0.75 * surf_rad * (2 * surf_rad * height + (height + surf_rad) * (height + pi * surf_rad))
180    return 0.5 * (ddd) ** (1. / 3.)
181
182# VR defaults to 1.0
183
184def random():
185    outer = 10**np.random.uniform(1, 4.7, size=3)
186    thick = np.random.beta(0.5, 0.5, size=3)*(outer-2) + 1
187    length = outer - thick
188    pars = dict(
189        length_a=length[0],
190        length_b=length[1],
191        length_c=length[2],
192        thick_rim_a=thick[0],
193        thick_rim_b=thick[1],
194        thick_rim_c=thick[2],
195    )
196    return pars
197
198# parameters for demo
199demo = dict(scale=1, background=0.0,
200            sld_core=1, sld_a=2, sld_b=4, sld_c=2, sld_solvent=6,
201            length_a=35, length_b=75, length_c=400,
202            thick_rim_a=10, thick_rim_b=10, thick_rim_c=10,
203            theta=0, phi=0, psi=0,
204            length_a_pd=0.1, length_a_pd_n=1,
205            length_b_pd=0.1, length_b_pd_n=1,
206            length_c_pd=0.1, length_c_pd_n=1,
207            thick_rim_a_pd=0.1, thick_rim_a_pd_n=1,
208            thick_rim_b_pd=0.1, thick_rim_b_pd_n=1,
209            thick_rim_c_pd=0.1, thick_rim_c_pd_n=1,
210            theta_pd=10, theta_pd_n=1,
211            phi_pd=10, phi_pd_n=1,
212            psi_pd=10, psi_pd_n=1)
213
214# rkh 7/4/17 add random unit test for 2d, note make all params different, 2d values not tested against other codes or models
215if 0:  # pak: model rewrite; need to update tests
216    qx, qy = 0.2 * cos(pi/6.), 0.2 * sin(pi/6.)
217    tests = [[{}, 0.2, 0.533149288477],
218             [{}, [0.2], [0.533149288477]],
219             [{'theta':10.0, 'phi':20.0}, (qx, qy), 0.0853299803222],
220             [{'theta':10.0, 'phi':20.0}, [(qx, qy)], [0.0853299803222]],
221            ]
222    del qx, qy  # not necessary to delete, but cleaner
Note: See TracBrowser for help on using the repository browser.