Loading...
Searching...
No Matches
SaddleSearchJob.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#include "eon/SaddleSearchJob.h"
13#ifdef WITH_ARTN
15#endif
16#include "eon/EonLogger.h"
17#include "eon/EpiCenters.h"
18#include "eon/HelperFunctions.h"
19#include "eon/Potential.h"
20
21#include <filesystem>
22#include <format>
23#include <fstream>
24#include <stdexcept>
25#include <string>
26
27namespace eonc {
28
29std::vector<std::string> SaddleSearchJob::run() {
30 std::string reactantFilename = eonc::helpers::getRelevantFile("pos.con");
31 std::string displacementFilename("displacement.con");
32 std::string modeFilename("direction.dat");
33
34 if (params.main_options().checkpoint) {
35 if (std::filesystem::exists("displacement_cp.con") &&
36 std::filesystem::exists("mode_cp.dat")) {
37 displacementFilename = "displacement_cp.con";
38 modeFilename = "mode_cp.dat";
39 QUILL_LOG_DEBUG(log, "Resuming from checkpoint");
40 } else {
41 QUILL_LOG_DEBUG(log, "No checkpoint files found");
42 }
43 }
44
45 initial = std::make_shared<Matter>(pot, params);
46 displacement = std::make_shared<Matter>(pot, params);
47 saddle = std::make_shared<Matter>(pot, params);
48
49 if (!eonc::io::io_ok(initial->con2matter(reactantFilename))) {
50 EONC_LOG_CRITICAL("Failed to load {}", reactantFilename);
51 throw std::runtime_error("failed to load " + reactantFilename);
52 }
53
54 const bool standaloneARTn = params.saddle_search_options().method == "artn";
55
56 AtomMatrix mode = AtomMatrix::Zero(initial->numberOfAtoms(), 3);
57 if (!standaloneARTn && params.saddle_search_options().displace_type ==
59 // Load displacement.con, or synthesize from pos.con + direction.dat (#79).
61 *saddle, *initial, displacementFilename, modeFilename,
62 params.saddle_search_options().displace_magnitude)) {
63 EONC_LOG_CRITICAL("Failed to load {} (and no usable {})",
64 displacementFilename, modeFilename);
65 throw std::runtime_error("missing displacement.con and direction.dat");
66 }
67 if (std::filesystem::exists(modeFilename)) {
68 mode = eonc::helpers::loadMode(modeFilename, initial->numberOfAtoms());
69 }
70 } else if (!standaloneARTn && eonc::helpers::applyClientDisplacement(
71 *saddle, *initial, params, &mode)) {
72 // listed_atoms / random / last_atom / least_coordinated / not_fcc_hcp
73 } else {
74 *saddle = *initial;
75 }
76
77 if (standaloneARTn && std::filesystem::exists(modeFilename)) {
78 mode = eonc::helpers::loadMode(modeFilename, initial->numberOfAtoms());
79 }
80
81 (void)runPrepared(mode);
82 return returnFiles;
83}
84
85std::shared_ptr<Matter>
86SaddleSearchJob::runFromMatter(std::shared_ptr<Matter> seed) {
87 if (!seed) {
88 throw std::runtime_error("SaddleSearchJob::runFromMatter: null Matter");
89 }
90 initial = seed;
91 initial->setPotential(pot);
92 displacement = std::make_shared<Matter>(pot, params);
93 saddle = std::make_shared<Matter>(pot, params);
94 AtomMatrix mode = AtomMatrix::Zero(initial->numberOfAtoms(), 3);
96 &mode)) {
97 *saddle = *initial;
98 }
100 return runPrepared(mode);
101}
102
103std::shared_ptr<Matter> SaddleSearchJob::runPrepared(const AtomMatrix &mode) {
104 const bool useStandaloneARTn =
105 params.saddle_search_options().method == "artn";
106 const bool useARTnAsMinMode =
107 params.saddle_search_options().method == "min_mode" &&
108 params.saddle_search_options().minmode_method == "artn";
109
110#ifdef WITH_ARTN
111 if (useStandaloneARTn || useARTnAsMinMode) {
113 std::make_unique<ARTnSaddleSearch>(saddle, pot, mode, params);
114 } else
115#endif
116 {
117#ifndef WITH_ARTN
118 if (useStandaloneARTn) {
119 throw std::runtime_error(
120 "saddle_search.method=artn requires a build with ARTn support");
121 }
122 if (useARTnAsMinMode) {
123 throw std::runtime_error(
124 "saddle_search.minmode_method=artn requires a build with ARTn "
125 "support");
126 }
127#endif
128 saddleSearch = std::make_unique<MinModeSaddleSearch>(
129 saddle, mode, initial->getPotentialEnergy(), params, pot);
130 }
131
132 int status = doSaddleSearch();
133 printEndState(status);
134 saveData(status);
135
136 return saddle;
137}
138
140 long status;
141 int f1{0};
142 f1 = this->pot->forceCallCounter;
143 try {
144 status = saddleSearch->run();
145 } catch (int e) {
146 if (e == 100) {
148 } else {
149 QUILL_LOG_ERROR(log, "unknown exception: {}", e);
150 throw e;
151 }
152 } catch (const std::exception &e) {
153 QUILL_LOG_ERROR(log, "Saddle search potential failed: {}", e.what());
155 }
156
157 if (params.saddle_search_options().method == "min_mode" &&
158 params.saddle_search_options().minmode_method ==
160 fCallsSaddle = saddleSearch->getForceCalls();
161 } else if (params.saddle_search_options().method == "artn") {
162 fCallsSaddle = saddleSearch->getForceCalls();
163 } else {
164 fCallsSaddle += this->pot->forceCallCounter - f1;
165 }
166
167 return status;
168}
169
171 std::string resultsFilename("results.dat");
172 returnFiles.push_back(resultsFilename);
173
174 std::ofstream out(resultsFilename, std::ios::binary);
175 if (out) {
176 out << std::format("{} termination_reason\n", status);
177 out << std::format("{} termination_reason_text\n",
178 saddleSearch->describeStatus(status));
179 out << "saddle_search job_type\n";
180 out << std::format("{} random_seed\n", params.main_options().randomSeed);
181 out << std::format(
182 "{} potential_type\n",
183 magic_enum::enum_name<PotType>(params.potential_options().potential));
184 out << std::format("{} total_force_calls\n",
185 this->pot->forceCallCounter.load());
186 out << std::format("{} force_calls_saddle\n", fCallsSaddle);
187 out << std::format("{} iterations\n", saddleSearch->getIterationCount());
189 out << std::format("{:f} potential_energy_saddle\n",
190 saddle->getPotentialEnergy());
191 out << std::format("{:f} final_eigenvalue\n",
192 saddleSearch->getEigenvalue());
193 }
194 out << std::format("{:f} potential_energy_reactant\n",
195 initial->getPotentialEnergy());
196 }
197
198 std::string modeFilename("mode.dat");
199 returnFiles.push_back(modeFilename);
200 eonc::helpers::saveMode(modeFilename, saddle, saddleSearch->getEigenvector());
201
202 std::string saddleFilename("saddle.con");
203 returnFiles.push_back(saddleFilename);
204 if (!eonc::io::io_ok(saddle->matter2con(saddleFilename))) {
205 QUILL_LOG_ERROR(log, "Failed to write {}", saddleFilename);
206 }
207}
208
210 auto msg = saddleSearch->describeStatus(status);
211 if (status == MinModeSaddleSearch::STATUS_GOOD) {
212 QUILL_LOG_DEBUG(log, "[Saddle Search] {}", msg);
213 } else {
214 QUILL_LOG_WARNING(log, "[Saddle Search] {}", msg);
215 }
216}
217
218} // namespace eonc
Eigen::Matrix< double, Eigen::Dynamic, 3, eOnStorageOrder > AtomMatrix
Definition Eigen.h:37
#define EONC_LOG_CRITICAL(...)
Definition EonLogger.h:267
Finds transition states by finding saddle points on the potential energy surface.
std::shared_ptr< Potential > pot
Definition Job.h:63
Parameters params
Definition Job.h:58
static const char MINMODE_GPRDIMER[]
std::unique_ptr< SaddleSearchMethod > saddleSearch
Initializes a ref SaddleSearchMethod (base class for polymorphism).
std::vector< std::string > returnFiles
Container for the results of the run.
std::shared_ptr< Matter > runFromMatter(std::shared_ptr< Matter > seed)
In-process entry: seed reactant Matter, no pos.con.
std::shared_ptr< Matter > saddle
Configuration used during the saddle point search.
eonc::log::Scoped log
std::vector< std::string > run(void) override
Kicks off the Saddle Search.
int doSaddleSearch()
Runs the correct saddle search; also checks if the run was successful.
int fCallsSaddle
Force calls to find the saddle.
std::shared_ptr< Matter > displacement
Configuration used during the saddle point search.
void saveData(int status)
Writes the results from the run to file.
void printEndState(int status)
Logs the run status and makes sure the run was successful.
std::shared_ptr< Matter > initial
Initial configuration.
std::shared_ptr< Matter > runPrepared(const AtomMatrix &mode)
const char DISP_LOAD[]
Definition EpiCenters.h:20
bool applyClientDisplacement(Matter &target, const Matter &initial, const Parameters &params, AtomMatrix *modeOut)
std::string getRelevantFile(std::string filename)
bool loadOrSynthesizeDisplacement(Matter &target, const Matter &initial, const std::string &displacementPath, const std::string &modePath, double scale)
AtomMatrix loadMode(FILE *modeFile, int nAtoms)
void saveMode(FILE *modeFile, std::shared_ptr< Matter > matter, AtomMatrix mode)
Write a mode; constrained axes are emitted as 0.
constexpr bool io_ok(IoStatus s) noexcept
Definition ConFileIO.h:38
RAII resource manager for the ARTn C library with global synchronization.