Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
Lattices/PeriodicLatticeInterpolant.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_PeriodicLatticeInterpolant_cpp_
9#define model_PeriodicLatticeInterpolant_cpp_
10
11#include <numbers>
12#include <PeriodicLatticeInterpolant.h>
13
14namespace model
15{
16
17
18
19
20/**********************************************************************/
21template <int dim>
22std::vector<typename PeriodicLatticeInterpolant<dim>::MatrixDim> PeriodicLatticeInterpolant<dim>::getSymMatrices(const int &rotSymm,
23 const std::vector<Eigen::Matrix<double, dim, 1>> &mirSymm)
24{
25 std::vector<MatrixDim> temp;
26 for (int k = 0; k < rotSymm; ++k)
27 { // apply rotations
28 const double theta(k * 2.0 * std::numbers::pi / rotSymm);
29 const double c(cos(theta));
30 const double s(sin(theta));
31 temp.push_back((MatrixDim() << c, -s, s, c).finished());
32 }
33
34 for (const auto &N : mirSymm)
35 { // apply mirSymm to each existing entry in temp
36 const double nNorm(N.norm());
37 if (nNorm > FLT_EPSILON)
38 {
39 const VectorDim n(N / nNorm);
40 const auto temp1 = temp;
41 for (const auto &m : temp1)
42 {
43 temp.push_back(m * (MatrixDim::Identity() - 2.0 * n * n.transpose())); // mirror symm
44 }
45 }
46 }
47 return temp;
48}
49
50/**********************************************************************/
51template <int dim>
52Eigen::MatrixXd PeriodicLatticeInterpolant<dim>::getSinCosCoeffs(const Eigen::Matrix<double, Eigen::Dynamic, dim + 1> &f) const
53{
60 Eigen::MatrixXd M(Eigen::MatrixXd::Zero(f.rows(), 2 * waveVectors.rows())); // sine and cosine coeffs for each row
61 Eigen::MatrixXd V(Eigen::MatrixXd::Zero(f.rows(), 1));
62 for (int i = 0; i < f.rows(); i++)
63 {
64 for (int j = 0; j < waveVectors.rows(); j++)
65 {
66 const auto sc(sinKXcosKX(j, f.template block<1, dim>(i, 0)));
67 M(i, 2 * j) = sc.first;
68 M(i, 2 * j + 1) = sc.second;
69 }
70 V(i) = f(i, 2);
71 }
72
73 // Some of the S and C coefficients may be identically zero. This means that some columns of M may be vanishing, we need to remove those colums
74 std::vector<int> nonZcols;
75 for (int j = 0; j < M.cols(); ++j)
76 {
77 if (M.col(j).squaredNorm() > FLT_EPSILON)
78 {
79 nonZcols.push_back(j);
80 }
81 }
82
83 Eigen::MatrixXd M1(M.rows(), nonZcols.size());
84 for (size_t j = 0; j < nonZcols.size(); ++j)
85 {
86 M1.col(j) = M.col(nonZcols[j]);
87 }
88
89 const Eigen::JacobiSVD<Eigen::MatrixXd> svd(M1);
90
91 // Solve
92 if (M1.rows() == M1.cols() && svd.rank() == M1.rows())
93 {
94 const double cond(svd.singularValues()(0) / svd.singularValues()(svd.singularValues().size() - 1));
95 if (cond > 1.0e3)
96 {
97 std::cout << "M1=\n"
98 << M1 << std::endl;
99 std::cout << "rank=" << svd.rank() << std::endl;
100 std::cout << "cond=" << cond << std::endl;
101 throw std::runtime_error("Bad condition number");
102 }
103 const Eigen::VectorXd x(M1.lu().solve(V));
104
105 Eigen::VectorXd x1(Eigen::VectorXd::Zero(M.cols()));
106 for (size_t j = 0; j < nonZcols.size(); ++j)
107 {
108 x1(nonZcols[j]) = x(j);
109 }
110 return Eigen::Map<Eigen::MatrixXd>(x1.data(), 2, x1.rows() / 2); // reshape
111 }
112 else
113 {
114 std::cout << "M=\n"
115 << M << std::endl;
116 std::cout << "M1=\n"
117 << M1 << std::endl;
118 std::cout << "M1 has size " << M1.rows() << "x" << M1.cols() << ",and rank=" << svd.rank() << std::endl;
119 throw std::runtime_error("M1 MUST BE SQUARE AND FULL RANK");
120 return Eigen::MatrixXd::Zero(1, 1);
121 }
122}
123
124/**********************************************************************/
125template <int dim>
126std::pair<double, double> PeriodicLatticeInterpolant<dim>::sinKXcosKX(const int &r, const VectorDim &x) const
127{
128 std::pair<double, double> sc(0.0, 0.0);
129 for (const auto &R : symMatrices)
130 {
131 const double KdotX(waveVectors.row(r).dot(R * x));
132 sc.first += sin(KdotX);
133 sc.second += cos(KdotX);
134 }
135 return sc;
136}
137
138/**********************************************************************/
139template <int dim>
141 const Eigen::Matrix<double, Eigen::Dynamic, dim> &waveVectors_in,
142 const Eigen::Matrix<double, Eigen::Dynamic, dim + 1> &f,
143 const int &rotSymm,
144 const std::vector<Eigen::Matrix<double, dim, 1>> &N) : // rotSymm only works for 2d, in 3d we need to prescride axis and n-fold symm
145/* init */ A(A_in)
146/* init */,B(2.0 * std::numbers::pi * A.inverse().transpose())
147/* init */,waveVectors((B * waveVectors_in.transpose()).transpose())
148/* init */,symMatrices(getSymMatrices(rotSymm, N))
149/* init */,points(f)
150/* init */,sinCosCoeffs(getSinCosCoeffs(f).transpose())
151{
154}
155
156/**********************************************************************/
157template <int dim>
159{
160 double temp(0.0);
161 for (int r = 0; r < waveVectors.rows(); ++r)
162 {
163 const auto sc(sinKXcosKX(r, x));
164 temp += sinCosCoeffs(r, 0) * sc.first + sinCosCoeffs(r, 1) * sc.second;
165 }
166 return temp;
167}
168
169template struct PeriodicLatticeInterpolant<2>;
170} // end namespace
171#endif
Eigen::Matrix3d M
Eigen::Vector3d V
c
Definition int_R.m:15
function int_R syms a b c u real f
Definition int_R.m:4
x
Definition int_R.m:12
Eigen::Matrix< double, 3, 3 > MatrixDim
Definition pyMoDELib.cxx:67
Eigen::MatrixXd getSinCosCoeffs(const Eigen::Matrix< double, Eigen::Dynamic, dim+1 > &f) const
const Eigen::Matrix< double, Eigen::Dynamic, dim+1 > points
const Eigen::Matrix< double, Eigen::Dynamic, dim > waveVectors
PeriodicLatticeInterpolant(const MatrixDim &A_in, const Eigen::Matrix< double, Eigen::Dynamic, dim > &waveVectors_in, const Eigen::Matrix< double, Eigen::Dynamic, dim+1 > &f, const int &rotSymm, const std::vector< Eigen::Matrix< double, dim, 1 > > &N)
const Eigen::Matrix< double, Eigen::Dynamic, 2 > sinCosCoeffs
std::pair< double, double > sinKXcosKX(const int &r, const VectorDim &x) const
static std::vector< MatrixDim > getSymMatrices(const int &rotSymm, const std::vector< Eigen::Matrix< double, dim, 1 > > &mirSymm)
int j
int k
int i
vertex temp
void t struct mesh * m