Loading...
Searching...
No Matches
AtomicGPDimer.cpp
Go to the documentation of this file.
1/*
2** This file is part of eOn.
3**
4** SPDX-License-Identifier: BSD-3-Clause
5**
6** Copyright (c) 2010--present, eOn Development Team
7** All rights reserved.
8**
9** Repo:
10** https://github.com/TheochemUI/eOn
11*/
12// An interface to the GPDimer library
13
14#include "eon/AtomicGPDimer.h"
15#include "eon/GPRHelpers.h"
16#include "eon/HelperFunctions.h"
17#include "eon/fpe_handler.h"
18#include <cassert>
19#include <cmath>
20#include <cstring>
21#include <stdexcept>
22
23#include "subprojects/gpr_optim/gpr/AtomicDimer.h"
24#include "subprojects/gpr_optim/gpr/auxiliary/ProblemSetUp.h"
25#include "subprojects/gpr_optim/structures/Structures.h"
26
27namespace eonc {
28
29namespace {
30
31// AtomMatrix is row-major N×3; gpr::Coord is row-major 1×(3N) with the same
32// flat packing [x0,y0,z0,x1,...].
33void copyAtomMatrixToCoord(const AtomMatrix &src, gpr::Coord &dst) {
34 dst.resize(1, static_cast<Eigen::Index>(src.size()));
35 if (src.size() > 0) {
36 std::memcpy(dst.data(), src.data(),
37 static_cast<size_t>(src.size()) * sizeof(double));
38 }
39}
40
41} // namespace
42
43const char AtomicGPDimer::OPT_SCG[] = "scg";
44const char AtomicGPDimer::OPT_LBFGS[] = "lbfgs";
45
46AtomicGPDimer::AtomicGPDimer(std::shared_ptr<Matter> matter,
47 const Parameters &params,
48 std::shared_ptr<Potential> pot)
50 if (!matter) {
51 throw std::invalid_argument("AtomicGPDimer: null Matter");
52 }
53 matterCenter = std::make_shared<Matter>(pot, params);
54 *matterCenter = *matter;
56 // XTBPot treats a non-zero box as periodic. Matter::computePotential sends
57 // a zero box when periodic boundaries are off; the GP force box must match.
58 const Matrix3d cell =
59 matter->getPeriodic() ? matter->getCell() : Matrix3d::Zero();
60 for (int i = 0; i < 9; i++) {
61 p.cell_dimensions.value[i] = cell.data()[i];
62 }
63}
64
66 Matrix3d box = Matrix3d::Zero();
67 for (int i = 0; i < 9; ++i) {
68 box.data()[i] = p.cell_dimensions.value[i];
69 }
70 return box;
71}
72
73void AtomicGPDimer::compute(std::shared_ptr<Matter> matter,
74 AtomMatrix initialDirectionAtomMatrix) {
75 // Saddle search moves this Matter after the solver is constructed.
76 *matterCenter = *matter;
78 copyAtomMatrixToCoord(matter->getPositionsFree(), R_init);
79 init_middle_point.clear();
81 init_observations.clear();
82 problem_setup.activateFrozenAtoms(
83 R_init, params.gpr_dimer_options().active_radius, atoms_config);
84 AtomMatrix freeOrient(matterCenter->numberOfFreeAtoms(), 3);
85 int j = 0;
86 for (int i = 0; i < matterCenter->numberOfAtoms(); i++) {
87 if (!matterCenter->getFixed(i)) {
88 freeOrient.row(j) = initialDirectionAtomMatrix.row(i);
89 j++;
90 if (j == matterCenter->numberOfFreeAtoms()) {
91 break;
92 }
93 }
94 }
95 copyAtomMatrixToCoord(freeOrient, orient_init);
98
99 auto potential = eonc::helpers::makePotential(params);
100 pot::PotentialWrapper wrapper(
101 [&potential](long N, const double *R, const int *atomicNrs, double *F,
102 double *U, double *variance, const double *box) {
103 potential->force(N, R, atomicNrs, F, U, variance, box);
104 });
105 // Restore traps if execute throws. The saddle-search catch must not
106 // leave later force calls running with traps still masked.
107 {
108 eonc::FPEGuard fpe;
109 atomic_dimer.execute(wrapper);
110 }
111 // Forcefully set the right positions
112 matter->setPositionsFreeV(atomic_dimer.getFinalCoordOfMidPoint());
113 this->totalIterations = atomic_dimer.getIterations();
114 this->totalForceCalls = atomic_dimer.getTotalForceCalls();
115 pot->forceCallCounter = atomic_dimer.getTotalForceCalls();
116 return;
117}
118
120 return atomic_dimer.getFinalCurvature();
121}
122
124 const gpr::Coord &orient = atomic_dimer.getFinalOrientation();
125 const long nFree = matterCenter->numberOfFreeAtoms();
126 const long nAtoms = matterCenter->numberOfAtoms();
127 if (nFree <= 0 || orient.size() != 3 * nFree) {
128 return AtomMatrix::Zero(nAtoms, 3);
129 }
130 AtomMatrix freeMode = Eigen::Map<const AtomMatrix>(orient.data(), nFree, 3);
131 if (nFree == nAtoms) {
132 return freeMode;
133 }
134 AtomMatrix full = AtomMatrix::Zero(nAtoms, 3);
135 long k = 0;
136 for (long i = 0; i < nAtoms; ++i) {
137 if (!matterCenter->getFixed(i)) {
138 full.row(i) = freeMode.row(k++);
139 }
140 }
141 return full;
142}
143
144} // namespace eonc
Eigen::Matrix< double, 3, 3, eOnStorageOrder > Matrix3d
Definition Eigen.h:35
Eigen::Matrix< double, Eigen::Dynamic, 3, eOnStorageOrder > AtomMatrix
Definition Eigen.h:37
gpr::AtomsConfiguration atoms_config
double getEigenvalue() override
gpr::Observation init_observations
AtomMatrix getEigenvector() override
std::shared_ptr< Matter > matterCenter
static const char OPT_SCG[]
Matrix3d forceBox() const
gpr::InputParameters p
gpr::Observation init_middle_point
void compute(std::shared_ptr< Matter > matter, AtomMatrix initialDirection) override
AtomicGPDimer(std::shared_ptr< Matter > matter, const Parameters &params, std::shared_ptr< Potential > pot)
atmd::AtomicDimer atomic_dimer
static const char OPT_LBFGS[]
aux::ProblemSetUp problem_setup
const Parameters & params
std::shared_ptr< Potential > pot
LowestEigenmode(std::shared_ptr< Potential > potPassed, const Parameters &parameters)
gpr::InputParameters eon_parameters_to_gpr(const Parameters &parameters)
Create a parameters object for gpr_dimer.
gpr::AtomsConfiguration eon_matter_to_atmconf(Matter *matter)
Create a configuration of atoms for gpr_dimer.
std::shared_ptr< Potential > makePotential(const Parameters &params)
RAII resource manager for the ARTn C library with global synchronization.