50 n += n.transpose().eval();
52 n(0, 0) = sxx + syy + szz;
53 n(1, 1) = sxx - syy - szz;
54 n(2, 2) = -sxx + syy - szz;
55 n(3, 3) = -sxx - syy + szz;
57 Eigen::SelfAdjointEigenSolver<Matrix4d> es(n);
58 Eigen::Vector4d maxv = es.eigenvectors().col(3);
60 double aa = maxv[0] * maxv[0];
61 double bb = maxv[1] * maxv[1];
62 double cc = maxv[2] * maxv[2];
63 double dd = maxv[3] * maxv[3];
64 double ab = maxv[0] * maxv[1];
65 double ac = maxv[0] * maxv[2];
66 double ad = maxv[0] * maxv[3];
67 double bc = maxv[1] * maxv[2];
68 double bd = maxv[1] * maxv[3];
69 double cd = maxv[2] * maxv[3];
71 R(0, 0) = aa + bb - cc - dd;
72 R(0, 1) = 2 * (bc - ad);
73 R(0, 2) = 2 * (bd + ac);
74 R(1, 0) = 2 * (bc + ad);
75 R(1, 1) = aa - bb + cc - dd;
76 R(1, 2) = 2 * (cd - ab);
77 R(2, 0) = 2 * (bd - ac);
78 R(2, 1) = 2 * (cd + ab);
79 R(2, 2) = aa - bb - cc + dd;
85 const double max_diff) {
90 Eigen::VectorXd c1(3);
91 Eigen::VectorXd c2(3);
93 c1[0] = r1.col(0).sum();
94 c1[1] = r1.col(1).sum();
95 c1[2] = r1.col(2).sum();
96 c2[0] = r2.col(0).sum();
97 c2[1] = r2.col(1).sum();
98 c2[2] = r2.col(2).sum();
102 for (
int i = 0; i < r1.rows(); i++) {
117 for (
int i = 0; i < r1.rows(); i++) {
118 double diff = (r2.row(i) - r1.row(i)).norm();
119 if (diff > max_diff) {
134 long nAtoms = positions.rows();
135 long dof = nAtoms * 3;
138 Eigen::Vector3d com = Eigen::Vector3d::Zero();
139 for (
long i = 0; i < nAtoms; ++i) {
140 com(0) += positions(i, 0);
141 com(1) += positions(i, 1);
142 com(2) += positions(i, 2);
144 com /=
static_cast<double>(nAtoms);
147 std::vector<Eigen::VectorXd> basis;
151 for (
int d = 0; d < 3; ++d) {
152 Eigen::VectorXd t = Eigen::VectorXd::Zero(dof);
153 for (
long j = 0; j < nAtoms; ++j) {
160 Eigen::VectorXd rx = Eigen::VectorXd::Zero(dof);
161 Eigen::VectorXd ry = Eigen::VectorXd::Zero(dof);
162 Eigen::VectorXd rz = Eigen::VectorXd::Zero(dof);
164 for (
long i = 0; i < nAtoms; ++i) {
165 double x = positions(i, 0) - com(0);
166 double y = positions(i, 1) - com(1);
167 double z = positions(i, 2) - com(2);
183 std::vector<Eigen::VectorXd> ortho;
186 for (
auto &v : basis) {
187 Eigen::VectorXd u = v;
188 for (
const auto &e : ortho) {
192 if (u.norm() > 1e-9) {
199 for (
const auto &e : ortho) {
200 step -= step.dot(e) * e;
205 std::shared_ptr<Matter> m2) {
209 if (m2->numberOfFixedAtoms() > 0) {
214 long n = r1_passed.size();
217 Eigen::VectorXd step(n);
218 Eigen::Map<const Eigen::VectorXd> r1_flat(r1_passed.data(), n);
219 Eigen::Map<const Eigen::VectorXd> r2_flat(r2.data(), n);
220 step = r2_flat - r1_flat;
226 Eigen::VectorXd result = r1_flat + step;
228 Eigen::Map<Eigen::VectorXd>(resultMat.data(), n) = result;
230 m2->setPositions(resultMat);
234 std::shared_ptr<Matter> m2) {
245 Eigen::VectorXd disp(3);
248 disp[0] = r12.col(0).sum();
249 disp[1] = r12.col(1).sum();
250 disp[2] = r12.col(2).sum();
253 for (
int i = 0; i < r1.rows(); i++) {
270 return v1.rowwise().norm().maxCoeff();
280 for (
long i = 0; i + 3 <= n; i += 3) {
281 double norm = v1.segment<3>(i).norm();
289 double norm = v1.tail(rem).norm();
299 for (
int i = 0; i < v1.rows(); i++) {
300 double norm = v1.row(i).norm();
301 if (norm >= cutoff) {
313 if (max > maxMotion) {
314 v2 *= maxMotion / max;
324 if (max > maxMotion) {
325 v2 *= maxMotion / max;
334 double max = v1.norm();
335 if (max > maxMotion) {
336 v2 *= maxMotion / max;
345 double max = v1.norm();
346 if (max > maxMotion) {
347 v2 *= maxMotion / max;
371 const AtomMatrix &r2,
int left,
int right,
double tolerance) {
372 return std::fabs((m1.
pbc(r1.row(left) - r2.row(right))).norm()) < tolerance &&
377bool identicalAugment(
int left,
const std::vector<std::vector<int>> &adj,
378 std::vector<int> &matchRight, std::vector<char> &seen) {
379 for (
int right : adj[
static_cast<size_t>(left)]) {
380 if (seen[
static_cast<size_t>(right)] != 0) {
383 seen[
static_cast<size_t>(right)] = 1;
384 const int taken = matchRight[
static_cast<size_t>(right)];
385 if (taken < 0 || identicalAugment(taken, adj, matchRight, seen)) {
386 matchRight[
static_cast<size_t>(right)] = left;
398 const double distanceDifference) {
401 if (r1.rows() != r2.rows()) {
404 const int nAtoms =
static_cast<int>(r1.rows());
405 const double tolerance = distanceDifference;
407 bool indexAligned =
true;
408 for (
int i = 0; i < nAtoms; i++) {
409 if (!pairInside(m1, m2, r1, r2, i, i, tolerance)) {
410 indexAligned =
false;
418 std::vector<std::vector<int>> adj(
static_cast<size_t>(nAtoms));
419 for (
int left = 0; left < nAtoms; left++) {
420 for (
int right = 0; right < nAtoms; right++) {
421 if (pairInside(m1, m2, r1, r2, left, right, tolerance)) {
422 adj[
static_cast<size_t>(left)].push_back(right);
427 std::vector<int> matchRight(
static_cast<size_t>(nAtoms), -1);
429 for (
int left = 0; left < nAtoms; left++) {
430 std::vector<char> seen(
static_cast<size_t>(nAtoms), 0);
431 if (identicalAugment(left, adj, matchRight, seen)) {
435 return matched == nAtoms;
439 const double distanceDifference) {
443 double tolerance = distanceDifference;
446 if (r1.rows() != r2.rows()) {
451 std::vector<std::set<atom, by_atom>> rdf1(r1.rows());
452 std::vector<std::set<atom, by_atom>> rdf2(r2.rows());
454 for (
int i2 = 0; i2 < r2.rows(); i2++) {
456 for (
int j2 = 0; j2 < r2.rows(); j2++) {
467 for (
int i1 = 0; i1 < r1.rows(); i1++) {
468 if (matches == i1 - 2) {
471 for (
int j1 = 0; j1 < r1.rows(); j1++) {
480 for (
int x = 0; x < r2.rows(); x++) {
481 auto it2 = rdf2[x].begin();
482 auto it = rdf1[i1].begin();
485 for (; it != rdf1[i1].end() && it2 != rdf2[x].end(); ++it, ++it2) {
488 if (std::fabs(k1.
r - k2.
r) < tolerance && k1.
z == k2.
z) {
495 if (
static_cast<size_t>(counter) == rdf1[i1].size() &&
496 it2 == rdf2[x].end()) {
504 return matches >= r1.rows();
508 if (minDistance <= 0)
514 double cut = minDistance;
515 double pushAparts = 500;
517 for (
int count = 0; count < pushAparts; count++) {
519 for (
int i = 0; i < r1.rows(); i++) {
520 for (
int j = i + 1; j < r1.rows(); j++) {
525 delta.row(0) = r1.row(i) - r1.row(j);
526 delta = m1->pbc(delta);
527 const double d = delta.norm();
539 for (
int axis = 0; axis <= 2; axis++) {
540 const double component = f * delta(0, axis) / d;
541 Force(i, axis) += component;
542 Force(j, axis) -= component;
550 m1->setPositions(r1);
553 r1 = m1->getPositions();
Eigen::Matrix< double, 3, 3, eOnStorageOrder > RotationMatrix
Eigen::Matrix< double, 3, 3, eOnStorageOrder > Matrix3d
Eigen::Matrix< double, 4, 4, eOnStorageOrder > Matrix4d
Eigen::Matrix< double, Eigen::Dynamic, 3, eOnStorageOrder > AtomMatrix
#define EONC_LOG_INFO(...)
const AtomMatrix & getPositions() const
void setPositions(const AtomMatrix &pos)
AtomMatrix pbc(const AtomMatrix &diff) const
double distance(long index1, long index2) const
long getAtomicNr(long int atom) const
RotationMatrix rotationExtract(const AtomMatrix r1, const AtomMatrix r2)
AtomMatrix maxAtomMotionApplied(const AtomMatrix v1, double maxMotion)
long numAtomsMoved(const AtomMatrix v1, double cutoff)
double maxAtomMotion(const AtomMatrix v1)
void pushApart(std::shared_ptr< Matter > m1, double minDistance)
bool rotationMatch(const Matter &m1, const Matter &m2, const double max_diff)
VectorXd maxMotionAppliedV(const VectorXd v1, double maxMotion)
void projectOutRotTrans(Eigen::VectorXd &step, const AtomMatrix &positions)
bool identical(const Matter &m1, const Matter &m2, const double distanceDifference)
VectorXd maxAtomMotionAppliedV(const VectorXd v1, double maxMotion)
double maxAtomMotionV(const VectorXd v1)
bool sortedR(const Matter &m1, const Matter &m2, const double distanceDifference)
void rotationRemove(const AtomMatrix r1, std::shared_ptr< Matter > m2)
AtomMatrix maxMotionApplied(const AtomMatrix v1, double maxMotion)
void translationRemove(Matter &m1, const AtomMatrix r1)
bool operator()(atom const &a, atom const &b) const