20 #include <gsl/gsl_linalg.h>
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}),
28 registerBasisVectors();
32 : mp_selection_rule(nullptr), m_a(a1), m_b(a2), m_c(a3), m_cache_ok(false)
36 registerBasisVectors();
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),
45 if (lattice.mp_selection_rule)
46 setSelectionRule(*lattice.mp_selection_rule);
47 registerBasisVectors();
52 delete mp_selection_rule;
61 if (mp_selection_rule)
68 computeReciprocalVectors();
84 kvector_t direction = h * b1 + k * b2 + l * b3;
85 return direction.
unit();
90 return std::abs(m_a.
dot(m_b.
cross(m_c)));
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));
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));
132 return vectorsWithinRadius(input_vector, nearest_coords, radius, m_ra, m_rb, m_rc, m_a, m_b,
156 kvector_t a2(-a / 2.0, std::sqrt(3.0) * a / 2.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);
190 void Lattice::registerBasisVectors()
192 if (!
parameter(XComponentName(
"BasisA"))) {
193 registerVector(
"BasisA", &m_a,
"nm");
194 registerVector(
"BasisB", &m_b,
"nm");
195 registerVector(
"BasisC", &m_c,
"nm");
199 void Lattice::computeReciprocalVectors()
const
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;
209 std::vector<kvector_t> Lattice::vectorsWithinRadius(
const kvector_t input_vector,
210 const ivector_t& nearest_coords,
double radius,
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));
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]);
226 if (mp_selection_rule && !mp_selection_rule->coordinateSelected(coords))
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);
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);
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());
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());
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());
257 gsl_linalg_LU_decomp(p_basisMatrix, p_perm, &s);
258 gsl_linalg_LU_invert(p_basisMatrix, p_perm, p_inverseMatrix);
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));
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));
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));
272 gsl_permutation_free(p_perm);
273 gsl_matrix_free(p_basisMatrix);
274 gsl_matrix_free(p_inverseMatrix);
279 delete mp_selection_rule;
280 mp_selection_rule = p_selection_rule.clone();
Defines classes ISelectionRule, SimpleSelectionRule.
Defines M_PI and some more mathematical constants.
Defines class RealParameter.
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.
T z() const
Returns z-component in cartesian coordinate system.
void setY(const T &a)
Sets y-component in cartesian coordinate system.
T y() const
Returns y-component in cartesian coordinate system.
T x() const
Returns x-component in cartesian coordinate system.
void setZ(const T &a)
Sets z-component in cartesian coordinate system.
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.
RealParameter * parameter(const std::string &name) const
Returns parameter with given 'name'.
Pure virtual base class for selection rules.
A lattice with three basis vectors.
void resetBasis(const kvector_t a1, const kvector_t a2, const kvector_t a3)
Resets the basis vectors.
ivector_t getNearestLatticeVectorCoordinates(const kvector_t vector_in) const
Returns the nearest lattice point from a given vector.
ivector_t getNearestReciprocalLatticeVectorCoordinates(const kvector_t vector_in) const
Returns the nearest reciprocal lattice point from a given vector.
void setSelectionRule(const ISelectionRule &p_selection_rule)
Sets a selection rule for the reciprocal vectors.
kvector_t getMillerDirection(double h, double k, double l) const
Returns normalized direction corresponding to the given Miller indices.
static Lattice createHCPLattice(double a, double c)
TODO: Clarify how this is meant: HCP is not a Bravais lattice.
void initialize() const
Initializes cached data.
static Lattice createBCTLattice(double a, double c)
Returns a body-centered cubic (cI) lattice with edge length a.
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.
Lattice createTransformedLattice(const Transform3D &transform) const
Creates transformed lattice.
double volume() const
Returns the volume of the unit cell.
static Lattice createTetragonalLattice(double a, double c)
Returns a primitive tetragonal (tP) lattice with square base edge a and height c.
static Lattice createFCCLattice(double a)
Returns a face-centered cubic (cF) lattice with edge length a.
static Lattice createHexagonalLattice(double a, double c)
Returns a primitive hexagonal (hP) lattice with hexagonal edge a and height c.
static Lattice createCubicLattice(double a)
Returns a primitive cubic (cP) lattice with edge length a.
void getReciprocalLatticeBasis(kvector_t &b1, kvector_t &b2, kvector_t &b3) const
Returns the reciprocal basis vectors.
void onChange() override
Action to be taken in inherited class when a parameter has changed.