Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
Lattices/Lattice.cpp
Go to the documentation of this file.
1/* This file is part of PIL, the Particle Interaction Library.
2 *
3 *
4 * MODEL is distributed without any warranty under the
5 * GNU General Public License (GPL) v2 <http://www.gnu.org/licenses/>.
6 */
7
8#ifndef model_Lattice_cpp_
9#define model_Lattice_cpp_
10
11#include <LatticeModule.h>
12
13namespace model
14{
15
16 template <int dim>
18 {
19
20 // Check that Q is orthogonal
21 const MatrixDimD QQT(Q * Q.transpose());
22 if ((QQT - MatrixDimD::Identity()).norm() > 2.0 * DBL_EPSILON * dim * dim)
23 {
24 std::cout << "Q=\n"
25 << Q << std::endl;
26 std::cout << "Q*Q^T=\n"
27 << QQT << std::endl;
28 throw std::runtime_error("ROTATION MATRIX IS NOT ORTHOGONAL.");
29// assert(false && "ROTATION MATRIX IS NOT ORTHOGONAL.");
30 }
31
32 // Check sure that C2G is proper
33 if(std::fabs(Q.determinant() - 1.0) > FLT_EPSILON)
34 {
35 throw std::runtime_error("ROTATION MATRIX IS NOT PROPER.");
36
37 }
38// assert(std::fabs(Q.determinant() - 1.0) < FLT_EPSILON && "ROTATION MATRIX IS NOT PROPER.");
39
40 // Check that A is full rank
41 if(std::fabs(A.determinant()) < FLT_EPSILON)
42 {
43 throw std::runtime_error("A matrix is singular");
44
45 }
46 return Q * A;
47 }
48
49 template <int dim>
51 /* init */ latticeBasis(getLatticeBasis(A,Q))
52 /* init */,reciprocalBasis(latticeBasis.inverse().transpose())
53 /* init */,C2G(Q)
54 {
55 }
56
57 template <int dim>
58 Eigen::Matrix<long int, dim, 1> Lattice<dim>::rationalApproximation(VectorDimD nd)
59 {
60 Eigen::Array<long int, dim, 1> nums = Eigen::Matrix<long int, dim, 1>::Zero();
61
62 if (nd.squaredNorm() > 0.0)
63 {
64 const Eigen::Array<double, dim, 1> nda(nd.array().abs()); // vector of close-to-integer numbers corresponding to lattice coordinates
65 size_t maxID = 0;
66 const double maxVal(nda.maxCoeff(&maxID));
67 nd /= maxVal; // make each value of nd in [-1:1]
68
69 nums = Eigen::Matrix<long int, dim, 1>::Ones();
70 Eigen::Array<long int, dim, 1> dens = Eigen::Matrix<long int, dim, 1>::Ones();
71 long int denProd = 1;
72
73 for (int k = 0; k < dim; ++k)
74 {
75 BestRationalApproximation bra(nd(k), 10000);
76
77 nums(k) = bra.num;
78 dens(k) = bra.den;
79 denProd *= bra.den;
80 }
81
82 for (int k = 0; k < dim; ++k)
83 {
84 nums(k) *= (denProd / dens(k));
85 }
86 }
87 return nums.matrix();
88 }
89
90 template <int dim>
92 {
93 VectorDimD nd(reciprocalBasis.transpose() * d);
94 return LatticeVectorType(nd.array().round().matrix().template cast<long int>().eval(), *this);
95 }
96
97 template <int dim>
99 {
100
101 const VectorDimD nd(reciprocalBasis.transpose() * d);
103
104 const double crossNorm(temp.cartesian().normalized().cross(d.normalized()).norm());
105 if (crossNorm > FLT_EPSILON)
106 {
107 std::cout << "input direction=" << d.normalized().transpose() << std::endl;
108 std::cout << "lattice direction=" << temp.cartesian().normalized().transpose() << std::endl;
109 std::cout << "cross product norm=" << std::setprecision(15) << std::scientific << crossNorm << std::endl;
110 throw std::runtime_error("LATTICE DIRECTION NOT FOUND");
111 }
113 }
114
115 template <int dim>
117 {
118
119 const VectorDimD nd(latticeBasis.transpose() * d);
121
122 const double crossNorm(temp.cartesian().normalized().cross(d.normalized()).norm());
123 if (crossNorm > FLT_EPSILON)
124 {
125 std::cout << "input direction=" << std::setprecision(15) << std::scientific << d.normalized().transpose() << std::endl;
126 std::cout << "reciprocal lattice direction=" << std::setprecision(15) << std::scientific << temp.cartesian().normalized().transpose() << std::endl;
127 std::cout << "cross product norm=" << std::setprecision(15) << std::scientific << crossNorm << std::endl;
128 throw std::runtime_error("RECIPROCAL LATTICE DIRECTION NOT FOUND");
129 }
131 }
132
133
134 template <int dim>
136 const typename BestRationalApproximation::LongIntType &maxDen ) const
137 {
138
140 const BestRationalApproximation bra(d.norm() / ld.cartesian().norm(), maxDen);
141 Rational rat(bra.num, bra.den);
142 RationalLatticeDirectionType rld(rat, ld);
143 if ((rld.cartesian() - d).squaredNorm() > FLT_EPSILON)
144 {
145 std::cout << "input vector=" << d.transpose() << std::endl;
146 std::cout << "lattice direction=" << ld.cartesian().transpose() << std::endl;
147 std::cout << "rational=" << rat << std::endl;
148 std::cout << "d.norm()/ld.cartesian().norm()=" << d.norm() / ld.cartesian().norm() << std::endl;
149 throw std::runtime_error("RationalLatticeDirectionType NOT FOUND");
150 }
151 return rld;
152 }
153
154 template <int dim>
156 {
157 return LatticeVectorType(p, *this);
158 }
159
160 template <int dim>
165 template class Lattice<3>;
166}
167#endif
Eigen::Matrix< double, dim, dim > MatrixDimD
LatticeVectorType snapToLattice(const VectorDimD &d) const
ReciprocalLatticeDirectionType reciprocalLatticeDirection(const VectorDimD &d) const
const MatrixDimD latticeBasis
const MatrixDimD C2G
LatticeVector< dim > LatticeVectorType
Lattice(const MatrixDimD &A, const MatrixDimD &Q)
LatticeVectorType latticeVector(const VectorDimD &p) const
LatticeDirection< dim > LatticeDirectionType
RationalLatticeDirectionType rationalLatticeDirection(const VectorDimD &d, const typename BestRationalApproximation::LongIntType &maxDen=1000) const
LatticeDirectionType latticeDirection(const VectorDimD &d) const
Eigen::Matrix< double, dim, 1 > VectorDimD
ReciprocalLatticeVector< dim > ReciprocalLatticeVectorType
RationalLatticeDirection< dim > RationalLatticeDirectionType
static Eigen::Matrix< long int, dim, 1 > rationalApproximation(VectorDimD nd)
ReciprocalLatticeDirection< dim > ReciprocalLatticeDirectionType
static MatrixDimD getLatticeBasis(const MatrixDimD &A, const MatrixDimD &Q)
const MatrixDimD reciprocalBasis
ReciprocalLatticeVectorType reciprocalLatticeVector(const VectorDimD &p) const
function infiniteDisplacement syms Ax Ay Az Bx By Bz qx qy qz u L x y z real A
Q
vertex p[3]
int k
vertex temp