8#ifndef model_PeriodicLatticeInterpolant_cpp_
9#define model_PeriodicLatticeInterpolant_cpp_
11#include <PeriodicLatticeInterpolant.h>
22 const std::vector<Eigen::Matrix<double, dim, 1>> &mirSymm)
24 std::vector<MatrixDim>
temp;
25 for (
int k = 0;
k < rotSymm; ++
k)
27 const double theta(
k * 2.0 * M_PI / rotSymm);
28 const double c(cos(theta));
29 const double s(sin(theta));
33 for (
const auto &
N : mirSymm)
35 const double nNorm(
N.norm());
36 if (nNorm > FLT_EPSILON)
39 const auto temp1 =
temp;
40 for (
const auto &
m : temp1)
42 temp.push_back(
m * (MatrixDim::Identity() - 2.0 * n *
n.transpose()));
59 Eigen::MatrixXd
M(Eigen::MatrixXd::Zero(
f.rows(), 2 * waveVectors.rows()));
60 Eigen::MatrixXd
V(Eigen::MatrixXd::Zero(
f.rows(), 1));
61 for (
int i = 0;
i <
f.rows();
i++)
63 for (
int j = 0;
j < waveVectors.rows();
j++)
65 const auto sc(sinKXcosKX(
j,
f.template block<1, dim>(
i, 0)));
66 M(
i, 2 *
j) = sc.first;
67 M(
i, 2 *
j + 1) = sc.second;
73 std::vector<int> nonZcols;
74 for (
int j = 0;
j <
M.cols(); ++
j)
76 if (
M.col(
j).squaredNorm() > FLT_EPSILON)
78 nonZcols.push_back(
j);
82 Eigen::MatrixXd M1(
M.rows(), nonZcols.size());
83 for (
size_t j = 0;
j < nonZcols.size(); ++
j)
85 M1.col(
j) =
M.col(nonZcols[
j]);
88 const Eigen::JacobiSVD<Eigen::MatrixXd> svd(M1);
91 if (M1.rows() == M1.cols() && svd.rank() == M1.rows())
93 const double cond(svd.singularValues()(0) / svd.singularValues()(svd.singularValues().size() - 1));
98 std::cout <<
"rank=" << svd.rank() << std::endl;
99 std::cout <<
"cond=" << cond << std::endl;
100 assert(cond < 1.0e3 &&
"Bad condition number");
102 const Eigen::VectorXd
x(M1.lu().solve(
V));
104 Eigen::VectorXd x1(Eigen::VectorXd::Zero(
M.cols()));
105 for (
size_t j = 0;
j < nonZcols.size(); ++
j)
107 x1(nonZcols[
j]) =
x(
j);
109 return Eigen::Map<Eigen::MatrixXd>(x1.data(), 2, x1.rows() / 2);
117 std::cout <<
"M1 has size " << M1.rows() <<
"x" << M1.cols() <<
",and rank=" << svd.rank() << std::endl;
118 assert(
false &&
"M1 MUST BE SQUARE AND FULL RANK");
119 return Eigen::MatrixXd::Zero(1, 1);
127 std::pair<double, double> sc(0.0, 0.0);
128 for (
const auto &R : symMatrices)
130 const double KdotX(waveVectors.row(r).dot(R *
x));
131 sc.first += sin(KdotX);
132 sc.second += cos(KdotX);
140 const Eigen::Matrix<double, Eigen::Dynamic, dim> &waveVectors_in,
141 const Eigen::Matrix<double, Eigen::Dynamic, dim + 1> &
f,
143 const std::vector<Eigen::Matrix<double, dim, 1>> &
N) :
146 B(2.0 * M_PI *
A.inverse().transpose())
148 waveVectors((
B * waveVectors_in.transpose()).transpose())
150 symMatrices(getSymMatrices(rotSymm,
N))
152 sinCosCoeffs(getSinCosCoeffs(
f).transpose())
160 double PeriodicLatticeInterpolant<dim>::operator()(
const VectorDim &
x)
const
163 for (
int r = 0;
r < waveVectors.rows(); ++
r)
165 const auto sc(sinKXcosKX(r,
x));
166 temp += sinCosCoeffs(r, 0) * sc.first + sinCosCoeffs(r, 1) * sc.second;
171template struct PeriodicLatticeInterpolant<2>;
initial point of the source segment B
function infiniteDisplacement syms Ax Ay Az Bx By Bz qx qy qz u L x y z real A
function int_R syms a b c u real f
Eigen::Matrix< double, 3, 1 > VectorDim
Eigen::Matrix< double, 3, 3 > MatrixDim
Eigen::MatrixXd getSinCosCoeffs(const Eigen::Matrix< double, Eigen::Dynamic, dim+1 > &f) const
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)
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)