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
27std::vector<std::string> SaddleSearchJob::run() {
28 std::string reactantFilename("pos.con");
29 std::string displacementFilename("displacement.con");
30 std::string modeFilename("direction.dat");
31
32 if (params.main_options.checkpoint) {
33 if (std::filesystem::exists("displacement_cp.con") &&
34 std::filesystem::exists("mode_cp.dat")) {
35 displacementFilename = "displacement_cp.con";
36 modeFilename = "mode_cp.dat";
37 QUILL_LOG_DEBUG(log, "Resuming from checkpoint");
38 } else {
39 QUILL_LOG_DEBUG(log, "No checkpoint files found");
40 }
41 }
42
43 initial = std::make_shared<Matter>(pot, params);
44 displacement = std::make_shared<Matter>(pot, params);
45 saddle = std::make_shared<Matter>(pot, params);
46
47 if (!eonc::io::io_ok(initial->con2matter(reactantFilename))) {
48 EONC_LOG_CRITICAL("Failed to load {}", reactantFilename);
49 throw std::runtime_error("failed to load " + reactantFilename);
50 }
51
52 const bool standaloneARTn = params.saddle_search_options.method == "artn";
53
54 if (!standaloneARTn && params.saddle_search_options.displace_type ==
56 // Load displacement.con, or synthesize from pos.con + direction.dat (#79).
58 *saddle, *initial, displacementFilename, modeFilename,
59 params.saddle_search_options.displace_magnitude)) {
60 EONC_LOG_CRITICAL("Failed to load {} (and no usable {})",
61 displacementFilename, modeFilename);
62 throw std::runtime_error("missing displacement.con and direction.dat");
63 }
64 } else {
65 *saddle = *initial;
66 }
67
68 AtomMatrix mode = AtomMatrix::Zero(initial->numberOfAtoms(), 3);
69 const bool canLoadMode =
70 params.saddle_search_options.displace_type == eonc::EpiCenters::DISP_LOAD;
71 if (canLoadMode && std::filesystem::exists(modeFilename)) {
72 mode = eonc::helpers::loadMode(modeFilename, initial->numberOfAtoms());
73 }
74
75 const bool useStandaloneARTn = params.saddle_search_options.method == "artn";
76 const bool useARTnAsMinMode =
77 params.saddle_search_options.method == "min_mode" &&
78 params.saddle_search_options.minmode_method == "artn";
79
80#ifdef WITH_ARTN
81 if (useStandaloneARTn || useARTnAsMinMode) {
83 std::make_unique<ARTnSaddleSearch>(saddle, pot, mode, params);
84 } else
85#endif
86 {
87#ifndef WITH_ARTN
88 if (useStandaloneARTn) {
89 throw std::runtime_error(
90 "saddle_search.method=artn requires a build with ARTn support");
91 }
92 if (useARTnAsMinMode) {
93 throw std::runtime_error(
94 "saddle_search.minmode_method=artn requires a build with ARTn "
95 "support");
96 }
97#endif
98 saddleSearch = std::make_unique<MinModeSaddleSearch>(
99 saddle, mode, initial->getPotentialEnergy(), params, pot);
100 }
101
102 int status = doSaddleSearch();
103 printEndState(status);
104 saveData(status);
105
106 return returnFiles;
107}
108
110 Matter matterTemp(pot, params);
111 long status;
112 int f1{0};
113 f1 = this->pot->forceCallCounter;
114 try {
115 status = saddleSearch->run();
116 } catch (int e) {
117 if (e == 100) {
119 } else {
120 printf("unknown exception: %i\n", e);
121 throw e;
122 }
123 }
124
125 if (params.saddle_search_options.method == "min_mode" &&
126 params.saddle_search_options.minmode_method ==
128 fCallsSaddle = saddleSearch->getForceCalls();
129 } else if (params.saddle_search_options.method == "artn") {
130 fCallsSaddle = saddleSearch->getForceCalls();
131 } else {
132 fCallsSaddle += this->pot->forceCallCounter - f1;
133 }
134
135 return status;
136}
137
139 std::string resultsFilename("results.dat");
140 returnFiles.push_back(resultsFilename);
141
142 std::ofstream out(resultsFilename, std::ios::binary);
143 if (out) {
144 out << std::format("{} termination_reason\n", status);
145 out << std::format("{} termination_reason_text\n",
146 saddleSearch->describeStatus(status));
147 out << "saddle_search job_type\n";
148 out << std::format("{} random_seed\n", params.main_options.randomSeed);
149 out << std::format(
150 "{} potential_type\n",
151 magic_enum::enum_name<PotType>(params.potential_options.potential));
152 out << std::format("{} total_force_calls\n",
153 this->pot->forceCallCounter.load());
154 out << std::format("{} force_calls_saddle\n", fCallsSaddle);
155 out << std::format("{} iterations\n", saddleSearch->getIterationCount());
157 out << std::format("{:f} potential_energy_saddle\n",
158 saddle->getPotentialEnergy());
159 out << std::format("{:f} final_eigenvalue\n",
160 saddleSearch->getEigenvalue());
161 }
162 out << std::format("{:f} potential_energy_reactant\n",
163 initial->getPotentialEnergy());
164 }
165
166 std::string modeFilename("mode.dat");
167 returnFiles.push_back(modeFilename);
168 eonc::helpers::saveMode(modeFilename, saddle, saddleSearch->getEigenvector());
169
170 std::string saddleFilename("saddle.con");
171 returnFiles.push_back(saddleFilename);
172 if (!eonc::io::io_ok(saddle->matter2con(saddleFilename))) {
173 QUILL_LOG_ERROR(log, "Failed to write {}", saddleFilename);
174 }
175}
176
178 auto msg = saddleSearch->describeStatus(status);
179 if (status == MinModeSaddleSearch::STATUS_GOOD) {
180 QUILL_LOG_DEBUG(log, "[Saddle Search] {}", msg);
181 } else {
182 QUILL_LOG_WARNING(log, "[Saddle Search] {}", msg);
183 }
184}
Eigen::Matrix< double, Eigen::Dynamic, 3, eOnStorageOrder > AtomMatrix
Definition Eigen.h:37
#define EONC_LOG_CRITICAL(...)
Definition EonLogger.h:268
Finds transition states by finding saddle points on the potential energy surface.
std::vector< std::string > run(void)
Kicks off the Saddle Search.
std::shared_ptr< Potential > pot
Definition Job.h:55
Parameters params
Definition Job.h:54
static const char MINMODE_GPRDIMER[]
void saveData(int status)
Writes the results from the run to file.
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 > saddle
Configuration used during the saddle point search.
eonc::log::Scoped log
int fCallsSaddle
Force calls to find the saddle.
std::shared_ptr< Matter > displacement
Configuration used during the saddle point search.
void printEndState(int status)
Logs the run status and makes sure the run was successful.
int doSaddleSearch()
Runs the correct saddle search; also checks if the run was successful.
std::shared_ptr< Matter > initial
Initial configuration.
const char DISP_LOAD[]
Definition EpiCenters.h:20
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