Skip to content
Snippets Groups Projects
Commit dd2dd6c6 authored by Van Herck, Walter's avatar Van Herck, Walter
Browse files

Provide prototype LatticeUtils and define/implement orientation with Miller indices

parent 707d73ff
No related branches found
No related tags found
No related merge requests found
// ************************************************************************** //
//
// BornAgain: simulate and fit scattering at grazing incidence
//
//! @file Core/Lattice/ILatticeOrientation.cpp
//! @brief Implements subclasses of ILatticeOrientation.
//!
//! @homepage http://www.bornagainproject.org
//! @license GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
// ************************************************************************** //
#include "ILatticeOrientation.h"
#include "EigenCore.h"
namespace {
bool ValidMillerIndex(MillerIndexOrientation::MillerIndex index);
bool ParallelMillerIndices(MillerIndexOrientation::MillerIndex index1,
MillerIndexOrientation::MillerIndex index2);
double SignForCrossProduct(MillerIndexOrientation::QComponent q1,
MillerIndexOrientation::QComponent q2);
MillerIndexOrientation::QComponent ThirdQComponent(MillerIndexOrientation::QComponent q1,
MillerIndexOrientation::QComponent q2);
void FillVectorInRow(Eigen::Matrix3d& matrix, kvector_t vec,
MillerIndexOrientation::QComponent row);
} // unnamed namespace
ILatticeOrientation::~ILatticeOrientation() =default;
MillerIndexOrientation::MillerIndexOrientation(const Lattice& primitive_lattice)
: m_prim_lattice(primitive_lattice)
, m_q1(QX), m_q2(QX)
, m_ind1 { 0, 0, 0 }
, m_ind2 { 0, 0, 0 }
{}
MillerIndexOrientation::~MillerIndexOrientation() =default;
void MillerIndexOrientation::alignQToMillerInidices(
MillerIndexOrientation::QComponent q1, MillerIndexOrientation::MillerIndex index1,
MillerIndexOrientation::QComponent q2, MillerIndexOrientation::MillerIndex index2)
{
m_q1 = q1;
m_q2 = q2;
m_ind1 = index1;
m_ind2 = index2;
if (!checkAlignment())
throw std::runtime_error("MillerIndexOrientation::alignQToMillerInidices: "
"invalid alignment parameters");
}
Transform3D MillerIndexOrientation::transformationMatrix() const
{
auto dir_1 = m_prim_lattice.getMillerDirection(m_ind1.h, m_ind1.k, m_ind1.l);
auto dir_2 = m_prim_lattice.getMillerDirection(m_ind2.h, m_ind2.k, m_ind2.l);
auto dir_2_parallel = dir_2.project(dir_1);
dir_2 = (dir_2 - dir_2_parallel).unit();
auto dir_3 = SignForCrossProduct(m_q1, m_q2) * dir_1.cross(dir_2);
auto q3 = ThirdQComponent(m_q1, m_q2);
Eigen::Matrix3d rot_matrix;
FillVectorInRow(rot_matrix, dir_1, m_q1);
FillVectorInRow(rot_matrix, dir_2, m_q2);
FillVectorInRow(rot_matrix, dir_3, q3);
return Transform3D(rot_matrix);
}
bool MillerIndexOrientation::checkAlignment() const
{
if (m_q1 == m_q2)
return false;
if (!ValidMillerIndex(m_ind1) || !ValidMillerIndex(m_ind2))
return false;
if (ParallelMillerIndices(m_ind1, m_ind2))
return false;
return true;
}
namespace {
bool ValidMillerIndex(MillerIndexOrientation::MillerIndex index)
{
return (index.h != 0 || index.k != 0 || index.l != 0);
}
bool ParallelMillerIndices(MillerIndexOrientation::MillerIndex index1,
MillerIndexOrientation::MillerIndex index2)
{
int ratio = 0;
if (index2.h != 0) {
ratio = index1.h / index2.h;
} else if (index2.k != 0) {
ratio = index1.k / index2.k;
} else if (index2.l != 0) {
ratio = index1.l / index2.l;
}
if (ratio == 0) return false;
return (index1.h == ratio*index2.h && index1.k == ratio*index2.k && index1.l == ratio*index2.l);
}
double SignForCrossProduct(MillerIndexOrientation::QComponent q1,
MillerIndexOrientation::QComponent q2)
{
if ((q1 == MillerIndexOrientation::QX && q2 == MillerIndexOrientation::QY) ||
(q1 == MillerIndexOrientation::QY && q2 == MillerIndexOrientation::QZ) ||
(q1 == MillerIndexOrientation::QZ && q2 == MillerIndexOrientation::QX) )
return 1.0;
return -1.0;
}
MillerIndexOrientation::QComponent ThirdQComponent(MillerIndexOrientation::QComponent q1,
MillerIndexOrientation::QComponent q2)
{
if (q1 != MillerIndexOrientation::QX && q2 != MillerIndexOrientation::QX)
return MillerIndexOrientation::QX;
if (q1 != MillerIndexOrientation::QY && q2 != MillerIndexOrientation::QY)
return MillerIndexOrientation::QY;
return MillerIndexOrientation::QZ;
}
void FillVectorInRow(Eigen::Matrix3d& mat, kvector_t vec,
MillerIndexOrientation::QComponent row)
{
int i = row == MillerIndexOrientation::QX ? 0
: row == MillerIndexOrientation::QY ? 1 : 2;
for (int j=0; j<3; ++j)
mat(i, j) = vec[j];
}
} // unnamed namespace
// ************************************************************************** //
//
// BornAgain: simulate and fit scattering at grazing incidence
//
//! @file Core/Lattice/ILatticeOrientation.h
//! @brief Defines interface ILatticeOrientation and subclasses.
//!
//! @homepage http://www.bornagainproject.org
//! @license GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
// ************************************************************************** //
#ifndef ILATTICEORIENTATION_H
#define ILATTICEORIENTATION_H
#include "Lattice.h"
#include "Transform3D.h"
class BA_CORE_API_ ILatticeOrientation
{
public:
virtual ~ILatticeOrientation();
virtual Transform3D transformationMatrix() const=0;
};
class BA_CORE_API_ MillerIndexOrientation : public ILatticeOrientation
{
public:
enum QComponent { QX, QY, QZ };
struct MillerIndex {
int h, k, l;
};
MillerIndexOrientation(const Lattice& primitive_lattice);
~MillerIndexOrientation() override;
void alignQToMillerInidices(QComponent q1, MillerIndex index1,
QComponent q2, MillerIndex index2);
Transform3D transformationMatrix() const override;
private:
bool checkAlignment() const;
Lattice m_prim_lattice;
QComponent m_q1, m_q2;
MillerIndex m_ind1, m_ind2;
};
#endif // ILATTICEORIENTATION_H
......@@ -68,8 +68,6 @@ void Lattice::initialize() const
kvector_t Lattice::getMillerDirection(int h, int k, int l) const
{
if (h*k*l == 0)
throw std::runtime_error("Lattice::getMillerDirection: not defined for (h,k,l) = (0,0,0)");
kvector_t b1, b2, b3;
getReciprocalLatticeBasis(b1, b2, b3);
kvector_t direction = h*b1 + k*b2 + l*b3;
......
// ************************************************************************** //
//
// BornAgain: simulate and fit scattering at grazing incidence
//
//! @file Core/Multilayer/LatticeUtils.cpp
//! @brief Implements factory functions for different types of lattices and orientations.
//!
//! @homepage http://www.bornagainproject.org
//! @license GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
// ************************************************************************** //
#include "LatticeUtils.h"
// ************************************************************************** //
//
// BornAgain: simulate and fit scattering at grazing incidence
//
//! @file Core/Multilayer/LatticeUtils.h
//! @brief Defines factory functions for different types of lattices and orientations.
//!
//! @homepage http://www.bornagainproject.org
//! @license GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
// ************************************************************************** //
#ifndef LATTICEUTILS_H
#define LATTICEUTILS_H
#include "Lattice.h"
#include "Vectors3D.h"
class ILatticeOrientation;
namespace LatticeUtils
{
Lattice CreateFCCLattice(double lattice_constant, const ILatticeOrientation& orientation);
} // namespace LatticeUtils
#endif // LATTICEUTILS_H
......@@ -28,6 +28,12 @@ Transform3D::Transform3D(const Transform3D& other)
{
}
Transform3D::Transform3D(const Eigen::Matrix3d& matrix)
: m_matrix(matrix)
{
m_inverse_matrix = m_matrix.inverse();
}
Transform3D Transform3D::createIdentity()
{
return Transform3D();
......@@ -212,12 +218,6 @@ bool Transform3D::isZRotation() const
return true;
}
Transform3D::Transform3D(const Eigen::Matrix3d& matrix)
: m_matrix(matrix)
{
m_inverse_matrix = m_matrix.inverse();
}
double BottomZ(const std::vector<kvector_t>& vertices, const Transform3D& rotation)
{
if (vertices.size()==0)
......
......@@ -34,6 +34,11 @@ public:
//! Copy constructor
Transform3D(const Transform3D& other);
#ifndef SWIG
//! Constructor from matrix (no checks if this is an element of SO(3)!)
Transform3D(const Eigen::Matrix3d& matrix);
#endif
//! Destructor
~Transform3D() {}
......@@ -103,7 +108,6 @@ public:
bool isZRotation() const;
private:
#ifndef SWIG
Transform3D(const Eigen::Matrix3d &matrix);
Eigen::Matrix3d m_matrix;
Eigen::Matrix3d m_inverse_matrix;
#endif
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment