source: sasmodels/sasmodels/models/parallelepiped.py @ deb7ee0

core_shell_microgelscostrafo411magnetic_modelrelease_v0.94release_v0.95ticket-1257-vesicle-productticket_1156ticket_1265_superballticket_822_more_unit_tests
Last change on this file since deb7ee0 was deb7ee0, checked in by gonzalezm, 8 years ago

Added four parallelepiped-like models

  • Property mode set to 100644
File size: 8.9 KB
Line 
1# parallelepiped model
2# Note: model title and parameter table are inserted automatically
3r"""
4The form factor is normalized by the particle volume.
5
6Definition
7----------
8
9| This model calculates the scattering from a rectangular parallelepiped (:num:`Figure #parallelepiped-image`).
10| If you need to apply polydispersity, see also :ref:`rectangular-prism`.
11
12.. _parallelepiped-image:
13
14.. figure:: img/parallelepiped.jpg
15
16   Parallelepiped with the corresponding definition of sides.
17
18.. note::
19
20   The edge of the solid must satisfy the condition that $A < B < C$.
21   This requirement is not enforced in the model, so it is up to the
22   user to check this during the analysis.
23
24The 1D scattering intensity $I(q)$ is calculated as:
25
26.. Comment by Miguel Gonzalez:
27   I am modifying the original text because I find the notation a little bit
28   confusing. I think that in most textbooks/papers, the notation P(Q) is
29   used for the form factor (adim, P(Q=0)=1), although F(q) seems also to
30   be used. But here (as for many other models), P(q) is used to represent
31   the scattering intensity (in cm-1 normally). It would be good to agree on
32   a common notation.
33
34.. math::
35
36    I(q) = \frac{\text{scale}}{V} (\Delta\rho \cdot V)^2 \left< P(q, \alpha) \right>
37    + \text{background}
38
39where the volume $V = A B C$, the contrast is defined as
40:math:`\Delta\rho = \rho_{\textstyle p} - \rho_{\textstyle solvent}`,
41$P(q, \alpha)$ is the form factor corresponding to a parallelepiped oriented
42at an angle $\alpha$ (angle between the long axis C and :math:`\vec q`),
43and the averaging $\left<\ldots\right>$ is applied over all orientations.
44
45Assuming $a = A/B < 1$, $b = B /B = 1$, and $c = C/B > 1$, the
46form factor is given by (Mittelbach and Porod, 1961)
47
48.. math::
49
50    P(q, \alpha) = \int_0^1 \phi_Q\left(\mu \sqrt{1-\sigma^2},a\right)
51        \left[S(\mu c \sigma/2)\right]^2 d\sigma
52
53with
54
55.. math::
56
57    \phi_Q(\mu,a) = \int_0^1
58        \left\{S\left[\frac{\mu}{2}\cos\left(\frac{\pi}{2}u\right)\right]
59               S\left[\frac{\mu a}{2}\sin\left(\frac{\pi}{2}u\right)\right]
60               \right\}^2 du
61
62    S(x) = \frac{\sin x}{x}
63
64    \mu = qB
65
66
67The scattering intensity per unit volume is returned in units of |cm^-1|.
68
69NB: The 2nd virial coefficient of the parallelepiped is calculated based on
70the averaged effective radius $(=\sqrt{A B / \pi})$ and
71length $(= C)$ values, and used as the effective radius for
72$S(q)$ when $P(q) \cdot S(q)$ is applied.
73
74To provide easy access to the orientation of the parallelepiped, we define
75three angles $\theta$, $\phi$ and $\Psi$. The definition of $\theta$ and
76$\phi$ is the same as for the cylinder model (see also figures below).
77
78.. Comment by Miguel Gonzalez:
79   The following text has been commented because I think there are two
80   mistakes. Psi is the rotational angle around C (but I cannot understand
81   what it means against the q plane) and psi=0 corresponds to a||x and b||y.
82
83   The angle $\Psi$ is the rotational angle around the $C$ axis against
84   the $q$ plane. For example, $\Psi = 0$ when the $B$ axis is parallel
85   to the $x$-axis of the detector.
86
87The angle $\Psi$ is the rotational angle around the $C$ axis.
88For $\theta = 0$ and $\phi = 0$, $\Psi = 0$ corresponds to the $B$ axis
89oriented parallel to the y-axis of the detector with $A$ along the z-axis.
90For other $\theta$, $\phi$ values, the parallelepiped has to be first rotated
91$\theta$ degrees around $z$ and $\phi$ degrees around $y$,
92before doing a final rotation of $\Psi$ degrees around the resulting $C$ to
93obtain the final orientation of the parallelepiped.
94For example, for $\theta = 0$ and $\phi = 90$, we have that $\Psi = 0$
95corresponds to $A$ along $x$ and $B$ along $y$,
96while for $\theta = 90$ and $\phi = 0$, $\Psi = 0$ corresponds to
97$A$ along $z$ and $B$ along $x$.
98
99.. _parallelepiped-orientation:
100
101.. figure:: img/parallelepiped_angles_definition.jpg
102
103    Definition of the angles for oriented parallelepipeds.
104
105.. figure:: img/parallelepiped_angles_examples.jpg
106
107    Examples of the angles for oriented parallelepipeds against the detector plane.
108
109For a given orientation of the parallelepiped, the 2D form factor is calculated as
110
111.. math::
112
113    P(q_x, q_y) = \left[\frac{sin(qA\cos\alpha/2)}{(qA\cos\alpha/2)}\right]^2
114                  \left[\frac{sin(qB\cos\beta/2)}{(qB\cos\beta/2)}\right]^2
115                  \left[\frac{sin(qC\cos\gamma/2)}{(qC\cos\gamma/2)}\right]^2
116
117with
118
119.. math::
120
121    \cos\alpha = \hat A \cdot \hat q, \;
122    \cos\beta  = \hat B \cdot \hat q, \;
123    \cos\gamma = \hat C \cdot \hat q
124
125and the scattering intensity as:
126
127.. math::
128
129    I(q_x, q_y) = \frac{\text{scale}}{V} V^2 \Delta\rho^2 P(q_x, q_y) + \text{background}
130
131.. Comment by Miguel Gonzalez:
132   This reflects the logic of the code, as in parallelepiped.c the call
133   to _pkernel returns P(q_x, q_y) and then this is multiplied by V^2 * (delta rho)^2.
134   And finally outside parallelepiped.c it will be multiplied by scale, normalized by
135   V and the background added. But mathematically it makes more sense to write
136   I(q_x, q_y) = \text{scale} V \Delta\rho^2 P(q_x, q_y) + \text{background},
137   with scale being the volume fraction.
138
139
140Validation
141----------
142
143Validation of the code was done by comparing the output of the 1D calculation
144to the angular average of the output of a 2D calculation over all possible
145angles. The Figure below shows the comparison where the solid dot refers to
146averaged 2D while the line represents the result of the 1D calculation (for
147the averaging, 76, 180, 76 points are taken for the angles of $\theta$,
148$\phi$, and $\Psi$ respectively).
149
150.. _parallelepiped-compare:
151
152.. figure:: img/parallelepiped_compare.png
153
154   Comparison between 1D and averaged 2D.
155
156This model is based on form factor calculations implemented in a c-library
157provided by the NIST Center for Neutron Research (Kline, 2006).
158
159"""
160
161import numpy as np
162from numpy import pi, inf, sqrt
163
164name = "parallelepiped"
165title = "Rectangular parallelepiped with uniform scattering length density."
166description = """
167    I(q)= scale*V*(sld - solvent_sld)^2*P(q,alpha)+background
168        P(q,alpha) = integral from 0 to 1 of ...
169           phi(mu*sqrt(1-sigma^2),a) * S(mu*c*sigma/2)^2 * dsigma
170        with
171            phi(mu,a) = integral from 0 to 1 of ..
172            (S((mu/2)*cos(pi*u/2))*S((mu*a/2)*sin(pi*u/2)))^2 * du
173            S(x) = sin(x)/x
174            mu = q*B
175        V: Volume of the rectangular parallelepiped
176        alpha: angle between the long axis of the
177            parallelepiped and the q-vector for 1D
178"""
179category = "shape:parallelepiped"
180
181#             ["name", "units", default, [lower, upper], "type","description"],
182parameters = [["sld", "1e-6/Ang^2", 4, [-inf, inf], "",
183               "Parallelepiped scattering length density"],
184              ["solvent_sld", "1e-6/Ang^2", 1, [-inf, inf], "",
185               "Solvent scattering length density"],
186              ["a_side", "Ang", 35, [0, inf], "volume",
187               "Shorter side of the parallelepiped"],
188              ["b_side", "Ang", 75, [0, inf], "volume",
189               "Second side of the parallelepiped"],
190              ["c_side", "Ang", 400, [0, inf], "volume",
191               "Larger side of the parallelepiped"],
192              ["theta", "degrees", 60, [-inf, inf], "orientation",
193               "In plane angle"],
194              ["phi", "degrees", 60, [-inf, inf], "orientation",
195               "Out of plane angle"],
196              ["psi", "degrees", 60, [-inf, inf], "orientation",
197               "Rotation angle around its own c axis against q plane"],
198             ]
199
200source = ["lib/J1.c", "lib/gauss76.c", "parallelepiped.c"]
201
202def ER(a_side, b_side, c_side):
203    """
204        Return effective radius (ER) for P(q)*S(q)
205    """
206
207    # surface average radius (rough approximation)
208    surf_rad = sqrt(a_side * b_side / pi)
209
210    ddd = 0.75 * surf_rad * (2 * surf_rad * c_side + (c_side + surf_rad) * (c_side + pi * surf_rad))
211    return 0.5 * (ddd) ** (1. / 3.)
212
213# VR defaults to 1.0
214
215# parameters for demo
216demo = dict(scale=1, background=0,
217            sld=6.3e-6, solvent_sld=1.0e-6,
218            a_side=35, b_side=75, c_side=400,
219            theta=45, phi=30, psi=15,
220            a_side_pd=0.1, a_side_pd_n=10,
221            b_side_pd=0.1, b_side_pd_n=1,
222            c_side_pd=0.1, c_side_pd_n=1,
223            theta_pd=10, theta_pd_n=1,
224            phi_pd=10, phi_pd_n=1,
225            psi_pd=10, psi_pd_n=10)
226
227# For testing against the old sasview models, include the converted parameter
228# names and the target sasview model name.
229oldname = 'ParallelepipedModel'
230oldpars = dict(theta='parallel_theta', phi='parallel_phi', psi='parallel_psi',
231               a_side='short_a', b_side='short_b', c_side='long_c',
232               sld='sldPipe', solvent_sld='sldSolv')
233
234
235qx, qy = 0.2 * np.cos(2.5), 0.2 * np.sin(2.5)
236tests = [[{}, 0.2, 0.17658004974],
237         [{}, [0.2], [0.17658004974]],
238         [{'theta':10.0, 'phi':10.0}, (qx, qy), 0.00460296014],
239         [{'theta':10.0, 'phi':10.0}, [(qx, qy)], [0.00460296014]],
240        ]
241del qx, qy  # not necessary to delete, but cleaner
Note: See TracBrowser for help on using the repository browser.