- Categories
- Parallelepiped
- Octahedron_truncated_txtytz
- octahedron_truncated_txtytz.py
Octahedron_truncated_txtytz - octahedron_truncated_txtytz.py
# octahedron model
# Note: model title and parameter table are inserted automatically
r"""
This model provides the form factor, $P(q)$, for a general octahedron
with the possibility to be truncated differently along 3 directions (x,y,z).
This model is constructed in a similar way as the octahedron_truncated model.
For example, it is suited to model square bipyramids or square bifrustum.
Definition
----------
The general octahedron is defined by its dimensions along its three perpendicular two-fold axis along x, y and z directions.
length_a, length_b and length_c are the distances from the center of the general octahedron to its 6 vertices.
Coordinates of the six vertices are :
(length_a,0,0)
(-length_a,0,0)
(0,length_b,0)
(0,-length_b,0)
(0,0,length_c)
(0,0,-length_c)
Coordinates of the six vertices are :
(length_a,0,0)
(-length_a,0,0)
(0,length_b,0)
(0,-length_b,0)
(0,0,length_c)
(0,0,-length_c)
tx, ty and tz are the three truncation parameters.
No truncation corresponds to tx=ty=tz=1.
Truncation adds a square facet for each vertice that is perpendicular to a 2-fold axis.
The resulting shape is made of 6 squares and 8 hexagons, that may be non regular depending on the dimensions.
A square facet crosses the x,y,z directions at distances equal to tx*length_a, ty*length_b and tz*length_c.
The model contains 6 parameters: length_a, the two ratios b2a_ratio and c2a_ratio and tx, ty and tz:
length_a
b2a_ratio = length_b/length_a
c2a_ratio = length_c/length_a
0 < tx < 1
0 < ty < 1
0 < tz < 1
For a regular shape:
b2a_ratio = c2a_ratio = 1
For example, a regular square bifrustum shape with the 4-fold axis along $z$ corresponds to :
b2a_ratio = c2a_ratio = 1
tx=ty=1
0<tz<1
An elongated square bipyramid shape without truncation with the 4-fold axis along $z$ corresponds to :
b2a_ratio = 1
c2a_ratio > 1
tx=ty=tz=1
.. math::
Volume of the shape is:
V = (4/3) * length_a * (length_a*b2a_ratio) * (length_a*c2a_ratio) * (1.-(1.-tx)^3-(1.-ty)^3-(1.-(1.-tz)^3)
Lengths of edges are equal to :
A_edge^2 = length_a^2+length_b^2
B_edge^2 = length_a^2+length_c^2
C_edge^2 = length_b^2+length_c^2
For a regular octahedron :
b2a_ratio = c2a_ratio = 1
A_edge = B_edge = C_edge = length_a*sqrt(2)
length_a = length_b = length_c = A_edge/sqrt(2)
V = (4/3) * length_a^3 = (sqrt(2)/3) * A_edge^3 * (1.-(1.-tx)^3-(1.-ty)^3-(1.-(1.-tz)^3)
Amplitude of the form factor AP is calculated with a scaled scattering vector (qx,qy,qz) :
AP = 6./(1.-(1.-tx)*(1.-tx)*(1.-tx)-(1.-ty)*(1.-ty)*(1.-ty)-(1.-tz)*(1.-tz)*(1.-tz))*(AA+BB+CC);
with:
AA = 1./((qy*qy-qz*qz)*(qy*qy-qx*qx))*1./2.*((qy-qx)*sin(qy*(1.-tx)-qx*tx)+(qy+qx)*sin(qy*(1.-tx)+qx*tx))+
1./((qz*qz-qx*qx)*(qz*qz-qy*qy))*1./2.*((qz-qx)*sin(qz*(1.-tx)-qx*tx)+(qz+qx)*sin(qz*(1.-tx)+qx*tx));
BB = 1./((qz*qz-qx*qx)*(qz*qz-qy*qy))*1./2.*((qz-qy)*sin(qz*(1.-ty)-qy*ty)+(qz+qy)*sin(qz*(1.-ty)+qy*ty))+
1./((qx*qx-qy*qy)*(qx*qx-qz*qz))*1./2.*((qx-qy)*sin(qx*(1.-ty)-qy*ty)+(qx+qy)*sin(qx*(1.-ty)+qy*ty));
CC = 1./((qx*qx-qy*qy)*(qx*qx-qz*qz))*1./2.*((qx-qz)*sin(qx*(1.-tz)-qz*tz)+(qx+qz)*sin(qx*(1.-tz)+qz*tz))+
1./((qy*qy-qz*qz)*(qy*qy-qx*qx))*1./2.*((qy-qz)*sin(qy*(1.-tz)-qz*tz)+(qy+qz)*sin(qy*(1.-tz)+qz*tz));
and :
Qx = q * sin_theta * cos_phi;
Qy = q * sin_theta * sin_phi
Qz = q * cos_theta
qx = Qx * length_a
qy = Qy * length_b
qz = Qz * length_c
$\theta$ is the angle between the scattering vector and the $z$ axis of the octahedron ($length_c$).
$\phi$ is the angle between the scattering vector (lying in the $xy$ plane) and the $x$ axis ($length_a$).
The normalized form factor in 1D is obtained averaging over all possible
orientations. Same code as for a rectangular prism.
.. math::
P(q) = \frac{2}{\pi} \int_0^{\frac{\pi}{2}} \,
\int_0^{\frac{\pi}{2}} A_P^2(q) \, \sin\theta \, d\theta \, d\phi
And the 1D scattering intensity is calculated as
.. math::
I(q) = \text{scale} \times V \times (\rho_\text{p} -
\rho_\text{solvent})^2 \times P(q)
where $V$ is the volume of the octahedron, $\rho_\text{p}$
is the scattering length inside the volume, $\rho_\text{solvent}$
is the scattering length of the solvent, and (if the data are in absolute
units) *scale* represents the volume fraction (which is unitless).
For 2d data the orientation of the particle is required, described using
angles $\theta$, $\phi$ and $\Psi$ as in the diagrams below, for further details
of the calculation and angular dispersions see :ref:`orientation` .
The angle $\Psi$ is the rotational angle around the long *C* axis. For example,
$\Psi = 0$ when the *B* axis is parallel to the *x*-axis of the detector.
For 2d, constraints must be applied during fitting to ensure that the inequality
$A < B < C$ is not violated, and hence the correct definition of angles is preserved. The calculation will not report an error,
but the results may be not correct.
.. figure:: img/parallelepiped_angle_definition.png
Definition of the angles for oriented core-shell parallelepipeds.
Note that rotation $\theta$, initially in the $xz$ plane, is carried out first, then
rotation $\phi$ about the $z$ axis, finally rotation $\Psi$ is now around the axis of the cylinder.
The neutron or X-ray beam is along the $z$ axis.
.. figure:: img/parallelepiped_angle_projection.png
Examples of the angles for oriented rectangular prisms against the
detector plane.
Validation
----------
Validation of the code is made using numerical checks.
References
----------
1. Wei-Ren Chen et al. “Scattering functions of Platonic solids”.
In:Journal of AppliedCrystallography - J APPL CRYST44 (June 2011).
DOI:10.1107/S0021889811011691
2. Croset, Bernard, "Form factor of any polyhedron: a general compact
formula and its singularities" In: J. Appl. Cryst. (2017). 50, 1245–1255
https://doi.org/10.1107/S1600576717010147
3. Wuttke, J. Numerically stable form factor of any polygon and polyhedron
J Appl Cryst 54, 580-587 (2021)
https://doi.org/10.1107/S160057672100171
Authorship and Verification
----------------------------
* **Authors: Marianne Imperor-Clerc (marianne.imperor@universite-paris-saclay.fr)
Helen Ibrahim (helenibrahim1@outlook.com)**
* **Last Modified by MI: 9 October 2020**
* **Last Reviewed by MI: March 2023:**
"""
import numpy as np
from numpy import inf
name = "octahedron_truncated_txtytz"
title = "Truncated Octahedron txtytz."
description = """
AP = 6./(1.-(1.-tx)*(1.-tx)*(1.-tx)-(1.-ty)*(1.-ty)*(1.-ty)-(1.-tz)*(1.-tz)*(1.-tz))*(AA+BB+CC);
const double AA = 1./(2*(qy*qy-qz*qz)*(qy*qy-qx*qx))*((qy-qx)*sin(qy*(1.-tx)-qx*tx)+(qy+qx)*sin(qy*(1.-tx)+qx*tx))+
1./(2*(qz*qz-qx*qx)*(qz*qz-qy*qy))*((qz-qx)*sin(qz*(1.-tx)-qx*tx)+(qz+qx)*sin(qz*(1.-tx)+qx*tx));
const double BB = 1./(2*(qz*qz-qx*qx)*(qz*qz-qy*qy))*((qz-qy)*sin(qz*(1.-ty)-qy*ty)+(qz+qy)*sin(qz*(1.-ty)+qy*ty))+
1./(2*(qx*qx-qy*qy)*(qx*qx-qz*qz))*((qx-qy)*sin(qx*(1.-ty)-qy*ty)+(qx+qy)*sin(qx*(1.-ty)+qy*ty));
const double CC = 1./(2*(qx*qx-qy*qy)*(qx*qx-qz*qz))*((qx-qz)*sin(qx*(1.-tz)-qz*tz)+(qx+qz)*sin(qx*(1.-tz)+qz*tz))+
1./(2*(qy*qy-qz*qz)*(qy*qy-qx*qx))*((qy-qz)*sin(qy*(1.-tz)-qz*tz)+(qy+qz)*sin(qy*(1.-tz)+qz*tz));
normalisation to 1. of AP at q = 0. Division by a Factor 4/3.
Qx = q * sin_theta * cos_phi;
Qy = q * sin_theta * sin_phi;
Qz = q * cos_theta;
qx = Qx * length_a;
qy = Qy * length_b;
qz = Qz * length_c;
0 < tx < 1
0 < ty < 1
0 < tz < 1
"""
category = "shape:parallelepiped"
# ["name", "units", default, [lower, upper], "type","description"],
parameters = [["sld", "1e-6/Ang^2", 128, [-inf, inf], "sld",
"Octahedron scattering length density"],
["sld_solvent", "1e-6/Ang^2", 9.4, [-inf, inf], "sld",
"Solvent scattering length density"],
["length_a", "Ang", 35, [0, inf], "volume",
"half height along a axis"],
["b2a_ratio", "", 1, [0, inf], "volume",
"Ratio b/a"],
["c2a_ratio", "", 1, [0, inf], "volume",
"Ratio c/a"],
["tx", "", 0.99, [0.0, 1.0], "volume",
"truncation along x axis"],
["ty", "", 0.99, [0.0, 1.0], "volume",
"truncation along y axis"],
["tz", "", 0.99, [0.0, 1.0], "volume",
"truncation along z axis"],
["theta", "degrees", 0, [-360, 360], "orientation",
"c axis to beam angle"],
["phi", "degrees", 0, [-360, 360], "orientation",
"rotation about beam"],
["psi", "degrees", 0, [-360, 360], "orientation",
"rotation about c axis"],
]
source = ["lib/gauss20.c", "octahedron_truncated_txtytz.c"]
# change to "lib/gauss76.c" or "lib/gauss150.c" to increase the number of integration points
# for the orientational average. Note that it will increase calculation times.
have_Fq = True
Back to Model
Download