BornAgain  1.18.0
Simulate and fit neutron and x-ray scattering at grazing incidence
Lattice.cpp
Go to the documentation of this file.
1 // ************************************************************************** //
2 //
3 // BornAgain: simulate and fit scattering at grazing incidence
4 //
5 //! @file Sample/Lattice/Lattice.cpp
6 //! @brief Implements class Lattice.
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************** //
14 
15 #include "Sample/Lattice/Lattice.h"
20 #include <gsl/gsl_linalg.h>
21 
23  : mp_selection_rule(nullptr), m_a({1.0, 0.0, 0.0}), m_b({0.0, 1.0, 0.0}), m_c({0.0, 0.0, 1.0}),
24  m_cache_ok(false)
25 {
26  setName("Lattice");
27  initialize();
29 }
30 
31 Lattice::Lattice(const kvector_t a1, const kvector_t a2, const kvector_t a3)
32  : mp_selection_rule(nullptr), m_a(a1), m_b(a2), m_c(a3), m_cache_ok(false)
33 {
34  setName("Lattice");
35  initialize();
37 }
38 
39 Lattice::Lattice(const Lattice& lattice)
40  : INode(), mp_selection_rule(nullptr), m_a(lattice.m_a), m_b(lattice.m_b), m_c(lattice.m_c),
41  m_cache_ok(false)
42 {
43  setName("Lattice");
44  initialize();
45  if (lattice.mp_selection_rule)
48 }
49 
51 {
52  delete mp_selection_rule;
53 }
54 
56 {
57  kvector_t a1 = transform.transformed(m_a);
58  kvector_t a2 = transform.transformed(m_b);
59  kvector_t a3 = transform.transformed(m_c);
60  Lattice result = {a1, a2, a3};
63  return result;
64 }
65 
66 void Lattice::initialize() const
67 {
69  m_cache_ok = true;
70 }
71 
72 void Lattice::resetBasis(const kvector_t a1, const kvector_t a2, const kvector_t a3)
73 {
74  m_a = a1;
75  m_b = a2;
76  m_c = a3;
77  onChange();
78 }
79 
80 kvector_t Lattice::getMillerDirection(double h, double k, double l) const
81 {
82  kvector_t b1, b2, b3;
83  getReciprocalLatticeBasis(b1, b2, b3);
84  kvector_t direction = h * b1 + k * b2 + l * b3;
85  return direction.unit();
86 }
87 
88 double Lattice::volume() const
89 {
90  return std::abs(m_a.dot(m_b.cross(m_c)));
91 }
92 
94 {
95  if (!m_cache_ok) {
96  initialize();
97  }
98  b1 = m_ra;
99  b2 = m_rb;
100  b3 = m_rc;
101  return;
102 }
103 
105 {
106  double a1_coord = vector_in.dot(m_ra) / M_TWOPI;
107  double a2_coord = vector_in.dot(m_rb) / M_TWOPI;
108  double a3_coord = vector_in.dot(m_rc) / M_TWOPI;
109  int c1 = static_cast<int>(std::floor(a1_coord + 0.5));
110  int c2 = static_cast<int>(std::floor(a2_coord + 0.5));
111  int c3 = static_cast<int>(std::floor(a3_coord + 0.5));
112  return ivector_t(c1, c2, c3);
113 }
114 
116 {
117  double b1_coord = vector_in.dot(m_a) / M_TWOPI;
118  double b2_coord = vector_in.dot(m_b) / M_TWOPI;
119  double b3_coord = vector_in.dot(m_c) / M_TWOPI;
120  int c1 = static_cast<int>(std::floor(b1_coord + 0.5));
121  int c2 = static_cast<int>(std::floor(b2_coord + 0.5));
122  int c3 = static_cast<int>(std::floor(b3_coord + 0.5));
123  return ivector_t(c1, c2, c3);
124 }
125 
126 std::vector<kvector_t> Lattice::reciprocalLatticeVectorsWithinRadius(const kvector_t input_vector,
127  double radius) const
128 {
129  if (!m_cache_ok)
130  initialize();
131  ivector_t nearest_coords = getNearestReciprocalLatticeVectorCoordinates(input_vector);
132  return vectorsWithinRadius(input_vector, nearest_coords, radius, m_ra, m_rb, m_rc, m_a, m_b,
133  m_c);
134 }
135 
137 {
138  kvector_t a1(a, 0.0, 0.0);
139  kvector_t a2(0.0, a, 0.0);
140  kvector_t a3(0.0, 0.0, a);
141  return Lattice(a1, a2, a3);
142 }
143 
145 {
146  double b = a / 2.0;
147  kvector_t a1(0.0, b, b);
148  kvector_t a2(b, 0.0, b);
149  kvector_t a3(b, b, 0.0);
150  return Lattice(a1, a2, a3);
151 }
152 
154 {
155  kvector_t a1(a, 0.0, 0.0);
156  kvector_t a2(-a / 2.0, std::sqrt(3.0) * a / 2.0, 0.0);
157  kvector_t a3(0.0, 0.0, c);
158  return Lattice(a1, a2, a3);
159 }
160 
162 {
163  kvector_t a1(a, 0.0, 0.0);
164  kvector_t a2(-a / 2.0, std::sqrt(3.0) * a / 2.0, 0);
165  kvector_t a3(a / 2.0, a / std::sqrt(3.0) / 2.0, c / 2.0);
166  return Lattice(a1, a2, a3);
167 }
168 
170 {
171  kvector_t a1(a, 0.0, 0.0);
172  kvector_t a2(0.0, a, 0.0);
173  kvector_t a3(0.0, 0.0, c);
174  return Lattice(a1, a2, a3);
175 }
176 
178 {
179  kvector_t a1(a, 0.0, 0.0);
180  kvector_t a2(0.0, a, 0.0);
181  kvector_t a3(a / 2.0, a / 2.0, c / 2.0);
182  return Lattice(a1, a2, a3);
183 }
184 
186 {
187  m_cache_ok = false;
188 }
189 
191 {
192  if (!parameter(XComponentName("BasisA"))) {
193  registerVector("BasisA", &m_a, "nm");
194  registerVector("BasisB", &m_b, "nm");
195  registerVector("BasisC", &m_c, "nm");
196  }
197 }
198 
200 {
201  kvector_t a23 = m_b.cross(m_c);
202  kvector_t a31 = m_c.cross(m_a);
203  kvector_t a12 = m_a.cross(m_b);
204  m_ra = M_TWOPI / m_a.dot(a23) * a23;
205  m_rb = M_TWOPI / m_b.dot(a31) * a31;
206  m_rc = M_TWOPI / m_c.dot(a12) * a12;
207 }
208 
209 std::vector<kvector_t> Lattice::vectorsWithinRadius(const kvector_t input_vector,
210  const ivector_t& nearest_coords, double radius,
211  const kvector_t v1, const kvector_t v2,
212  const kvector_t v3, const kvector_t rec1,
213  const kvector_t rec2,
214  const kvector_t rec3) const
215 {
216  int max_X = static_cast<int>(std::floor(rec1.mag() * radius / M_TWOPI + 0.5));
217  int max_Y = static_cast<int>(std::floor(rec2.mag() * radius / M_TWOPI + 0.5));
218  int max_Z = static_cast<int>(std::floor(rec3.mag() * radius / M_TWOPI + 0.5));
219 
220  std::vector<kvector_t> ret;
221  for (int index_X = -max_X; index_X <= max_X; ++index_X) {
222  for (int index_Y = -max_Y; index_Y <= max_Y; ++index_Y) {
223  for (int index_Z = -max_Z; index_Z <= max_Z; ++index_Z) {
224  ivector_t coords(index_X + nearest_coords[0], index_Y + nearest_coords[1],
225  index_Z + nearest_coords[2]);
227  continue;
228  kvector_t latticePoint = coords[0] * v1 + coords[1] * v2 + coords[2] * v3;
229  if ((latticePoint - input_vector).mag() <= radius)
230  ret.push_back(latticePoint);
231  }
232  }
233  }
234  return ret;
235 }
236 
238  kvector_t o1, kvector_t o2, kvector_t o3)
239 {
240  gsl_matrix* p_basisMatrix = gsl_matrix_alloc(3, 3);
241  gsl_matrix* p_inverseMatrix = gsl_matrix_alloc(3, 3);
242  gsl_permutation* p_perm = gsl_permutation_alloc(3);
243  int s;
244 
245  gsl_matrix_set(p_basisMatrix, 0, 0, v1.x());
246  gsl_matrix_set(p_basisMatrix, 0, 1, v2.x());
247  gsl_matrix_set(p_basisMatrix, 0, 2, v3.x());
248 
249  gsl_matrix_set(p_basisMatrix, 1, 0, v1.y());
250  gsl_matrix_set(p_basisMatrix, 1, 1, v2.y());
251  gsl_matrix_set(p_basisMatrix, 1, 2, v3.y());
252 
253  gsl_matrix_set(p_basisMatrix, 2, 0, v1.z());
254  gsl_matrix_set(p_basisMatrix, 2, 1, v2.z());
255  gsl_matrix_set(p_basisMatrix, 2, 2, v3.z());
256 
257  gsl_linalg_LU_decomp(p_basisMatrix, p_perm, &s);
258  gsl_linalg_LU_invert(p_basisMatrix, p_perm, p_inverseMatrix);
259 
260  o1.setX(gsl_matrix_get(p_inverseMatrix, 0, 0));
261  o1.setY(gsl_matrix_get(p_inverseMatrix, 1, 0));
262  o1.setZ(gsl_matrix_get(p_inverseMatrix, 2, 0));
263 
264  o2.setX(gsl_matrix_get(p_inverseMatrix, 0, 1));
265  o2.setY(gsl_matrix_get(p_inverseMatrix, 1, 1));
266  o2.setZ(gsl_matrix_get(p_inverseMatrix, 2, 1));
267 
268  o3.setX(gsl_matrix_get(p_inverseMatrix, 0, 2));
269  o3.setY(gsl_matrix_get(p_inverseMatrix, 1, 2));
270  o3.setZ(gsl_matrix_get(p_inverseMatrix, 2, 2));
271 
272  gsl_permutation_free(p_perm);
273  gsl_matrix_free(p_basisMatrix);
274  gsl_matrix_free(p_inverseMatrix);
275 }
276 
277 void Lattice::setSelectionRule(const ISelectionRule& p_selection_rule)
278 {
279  delete mp_selection_rule;
280  mp_selection_rule = p_selection_rule.clone();
281 }
Defines classes ISelectionRule, SimpleSelectionRule.
Defines class Lattice.
Defines M_PI and some more mathematical constants.
#define M_TWOPI
Definition: MathConstants.h:49
Defines class RealParameter.
Declares class Transform3D.
BasicVector3D< int > ivector_t
Definition: Vectors3D.h:20
auto dot(const BasicVector3D< U > &v) const
Returns dot product of vectors (antilinear in the first [=self] argument).
BasicVector3D< T > unit() const
Returns unit vector in direction of this. Throws for null vector.
double mag() const
Returns magnitude of the vector.
void setX(const T &a)
Sets x-component in cartesian coordinate system.
Definition: BasicVector3D.h:71
T z() const
Returns z-component in cartesian coordinate system.
Definition: BasicVector3D.h:68
void setY(const T &a)
Sets y-component in cartesian coordinate system.
Definition: BasicVector3D.h:73
T y() const
Returns y-component in cartesian coordinate system.
Definition: BasicVector3D.h:66
T x() const
Returns x-component in cartesian coordinate system.
Definition: BasicVector3D.h:64
void setZ(const T &a)
Sets z-component in cartesian coordinate system.
Definition: BasicVector3D.h:75
auto cross(const BasicVector3D< U > &v) const
Returns cross product of vectors (linear in both arguments).
Base class for tree-like structures containing parameterized objects.
Definition: INode.h:49
RealParameter * parameter(const std::string &name) const
Returns parameter with given 'name'.
static std::string XComponentName(const std::string &base_name)
void setName(const std::string &name)
void registerVector(const std::string &base_name, kvector_t *p_vec, const std::string &units="nm")
Pure virtual base class for selection rules.
virtual bool coordinateSelected(const ivector_t &coordinate) const =0
virtual ISelectionRule * clone() const =0
A lattice with three basis vectors.
Definition: Lattice.h:28
bool m_cache_ok
Boolean indicating if the reciprocal vectors are already initialized in the cache.
Definition: Lattice.h:116
std::vector< kvector_t > vectorsWithinRadius(const kvector_t input_vector, const ivector_t &nearest_coords, double radius, const kvector_t v1, const kvector_t v2, const kvector_t v3, const kvector_t rec1, const kvector_t rec2, const kvector_t rec3) const
Definition: Lattice.cpp:209
void resetBasis(const kvector_t a1, const kvector_t a2, const kvector_t a3)
Resets the basis vectors.
Definition: Lattice.cpp:72
void registerBasisVectors()
Definition: Lattice.cpp:190
ivector_t getNearestLatticeVectorCoordinates(const kvector_t vector_in) const
Returns the nearest lattice point from a given vector.
Definition: Lattice.cpp:104
static void computeInverseVectors(const kvector_t v1, const kvector_t v2, const kvector_t v3, kvector_t o1, kvector_t o2, kvector_t o3)
Definition: Lattice.cpp:237
ivector_t getNearestReciprocalLatticeVectorCoordinates(const kvector_t vector_in) const
Returns the nearest reciprocal lattice point from a given vector.
Definition: Lattice.cpp:115
kvector_t m_b
Definition: Lattice.h:113
void setSelectionRule(const ISelectionRule &p_selection_rule)
Sets a selection rule for the reciprocal vectors.
Definition: Lattice.cpp:277
Lattice()
Definition: Lattice.cpp:22
kvector_t getMillerDirection(double h, double k, double l) const
Returns normalized direction corresponding to the given Miller indices.
Definition: Lattice.cpp:80
static Lattice createHCPLattice(double a, double c)
TODO: Clarify how this is meant: HCP is not a Bravais lattice.
Definition: Lattice.cpp:161
kvector_t m_c
Basis vectors in real space.
Definition: Lattice.h:113
void initialize() const
Initializes cached data.
Definition: Lattice.cpp:66
static Lattice createBCTLattice(double a, double c)
Returns a body-centered cubic (cI) lattice with edge length a.
Definition: Lattice.cpp:177
std::vector< kvector_t > reciprocalLatticeVectorsWithinRadius(const kvector_t input_vector, double radius) const
Computes a list of reciprocal lattice vectors within a specified distance of a given vector.
Definition: Lattice.cpp:126
kvector_t m_rc
Cache of basis vectors in reciprocal space.
Definition: Lattice.h:114
Lattice createTransformedLattice(const Transform3D &transform) const
Creates transformed lattice.
Definition: Lattice.cpp:55
ISelectionRule * mp_selection_rule
Definition: Lattice.h:112
double volume() const
Returns the volume of the unit cell.
Definition: Lattice.cpp:88
static Lattice createTetragonalLattice(double a, double c)
Returns a primitive tetragonal (tP) lattice with square base edge a and height c.
Definition: Lattice.cpp:169
void computeReciprocalVectors() const
Definition: Lattice.cpp:199
static Lattice createFCCLattice(double a)
Returns a face-centered cubic (cF) lattice with edge length a.
Definition: Lattice.cpp:144
kvector_t m_ra
Definition: Lattice.h:114
static Lattice createHexagonalLattice(double a, double c)
Returns a primitive hexagonal (hP) lattice with hexagonal edge a and height c.
Definition: Lattice.cpp:153
static Lattice createCubicLattice(double a)
Returns a primitive cubic (cP) lattice with edge length a.
Definition: Lattice.cpp:136
kvector_t m_a
Definition: Lattice.h:113
~Lattice() override
Definition: Lattice.cpp:50
void getReciprocalLatticeBasis(kvector_t &b1, kvector_t &b2, kvector_t &b3) const
Returns the reciprocal basis vectors.
Definition: Lattice.cpp:93
void onChange() override
Action to be taken in inherited class when a parameter has changed.
Definition: Lattice.cpp:185
kvector_t m_rb
Definition: Lattice.h:114
Vector transformations in three dimensions.
Definition: Transform3D.h:28
ivector_t transformed(const ivector_t &v) const
Return transformed vector v.
const double radius(5 *Units::nanometer)