41 std::string displacementFilename(
"displacement.con");
42 std::string modeFilename(
"direction.dat");
45 if (
params.saddle_search_options().method ==
"min_mode" ||
46 params.saddle_search_options().method ==
"basin_hopping" ||
47 params.saddle_search_options().method ==
"bgsd") {
49 }
else if (
params.saddle_search_options().method ==
"dynamics") {
56 std::shared_ptr<Potential> min2Pot =
pot;
57 if (
pot->needsPerImageInstance() &&
params.main_options().parallel) {
58 auto cloned =
pot->clonePotential();
62 min2 = std::make_shared<Matter>(min2Pot,
params);
66 throw std::runtime_error(
"failed to load " + reactantFilename);
69 if (
params.process_search_options().minimize_first) {
70 QUILL_LOG_DEBUG(
log,
"Minimizing initial structure\n");
71 fctmp =
initial->getPotentialCalls();
74 QUILL_LOG_DEBUG(
log,
"Initial minimization took {} fcalls",
75 initial->getPotentialCalls() - fctmp);
82 if (
params.saddle_search_options().method ==
"min_mode" ||
83 params.saddle_search_options().method ==
"basin_hopping" ||
84 params.saddle_search_options().method ==
"bgsd") {
85 if (
params.saddle_search_options().displace_type ==
91 params.saddle_search_options().displace_magnitude)) {
93 displacementFilename, modeFilename);
94 throw std::runtime_error(
"failed to load " + displacementFilename);
110 min2->setPotential(min2Pot);
112 const bool useARTnAsMinMode =
113 params.saddle_search_options().method ==
"min_mode" &&
114 params.saddle_search_options().minmode_method ==
"artn";
116 if (
params.saddle_search_options().method ==
"min_mode") {
117 if (
params.saddle_search_options().displace_type ==
119 std::filesystem::exists(modeFilename)) {
125 if (useARTnAsMinMode) {
135 }
else if (
params.saddle_search_options().method ==
"artn") {
139 if (
params.saddle_search_options().displace_type ==
141 std::filesystem::exists(modeFilename)) {
148 }
else if (
params.saddle_search_options().method ==
"basin_hopping") {
151 }
else if (
params.saddle_search_options().method ==
"dynamics") {
153 }
else if (
params.saddle_search_options().method ==
"bgsd") {
154 saddleSearch = std::make_unique<BiasedGradientSquaredDescent>(
163 if (
params.saddle_search_options().method ==
"artn") {
164 throw std::runtime_error(
165 "saddle_search.method=artn requires a build with ARTn support "
166 "(reconfigure with -Dwith_artn=true)");
168 if (useARTnAsMinMode) {
169 throw std::runtime_error(
170 "saddle_search.minmode_method=artn requires a build with ARTn "
171 "support (reconfigure with -Dwith_artn=true)");
176 throw std::runtime_error(
"unknown saddle_search.method");
183std::shared_ptr<Matter>
186 throw std::runtime_error(
"ProcessSearchJob::runFromMatter: null Matter");
192 std::shared_ptr<Potential> min2Pot =
pot;
193 if (
pot->needsPerImageInstance() &&
params.main_options().parallel) {
194 auto cloned =
pot->clonePotential();
200 min2 = std::make_shared<Matter>(min2Pot,
params);
208 min2->setPotential(min2Pot);
209 if (
params.saddle_search_options().method ==
"min_mode") {
212 }
else if (
params.saddle_search_options().method ==
"basin_hopping") {
215 }
else if (
params.saddle_search_options().method ==
"dynamics") {
217 }
else if (
params.saddle_search_options().method ==
"bgsd") {
218 saddleSearch = std::make_unique<BiasedGradientSquaredDescent>(
221 throw std::runtime_error(
222 "ProcessSearchJob::runFromMatter: unsupported saddle_search.method");
229 throw std::runtime_error(
"unknown saddle_search.method");
245 fctmp =
pot->forceCallCounter;
247 if (
params.saddle_search_options().method ==
"min_mode" &&
248 params.saddle_search_options().minmode_method ==
251 }
else if (
params.saddle_search_options().method ==
"artn") {
256 EONC_LOG_DEBUG(
"Got {} calls in the saddle search, with previous {}",
268 const auto min1Pot =
min1->getPotential();
269 const auto min2Pot =
min2->getPotential();
271 min1->setPotential(min1Pot);
275 params.process_search_options().minimization_offset;
276 min1->setPositions(displacedPos);
279 min2->setPotential(min2Pot);
282 params.process_search_options().minimization_offset;
283 min2->setPositions(displacedPos);
288 QUILL_LOG_DEBUG(
log,
"Starting Minimization 1 & 2");
289 bool converged1{
false}, converged2{
false};
290 long fc1_before =
min1->getPotentialCalls();
291 long fc2_before =
min2->getPotentialCalls();
296 (
pot->needsPerImageInstance() &&
297 min1->getPotential().get() !=
min2->getPotential().get());
298 if (
params.main_options().parallel && canParallel) {
302 std::exception_ptr t1Error;
305 converged1 =
min1->relax(
false,
params.debug_options().write_movies,
308 t1Error = std::current_exception();
312 converged2 =
min2->relax(
false,
params.debug_options().write_movies,
320 std::rethrow_exception(t1Error);
323 min1->relax(
false,
params.debug_options().write_movies,
false,
"min1");
325 min2->relax(
false,
params.debug_options().write_movies,
false,
"min2");
328 if (
min1->getPotential().get() ==
min2->getPotential().get()) {
332 (
min2->getPotentialCalls() - fc2_before);
334 QUILL_LOG_DEBUG(
log,
"Min1: {} fcalls, Min2: {} fcalls",
335 min1->getPotentialCalls() - fc1_before,
336 min2->getPotentialCalls() - fc2_before);
338 if (!converged1 || !converged2) {
359 params.structure_comparison_options().distance_difference;
360 auto countMoved = [&](
const Matter &m) {
362 for (
long i = 0; i <
initial->numberOfAtoms(); ++i) {
364 ->
pbc(
initial->getPositions().row(i) - m.getPositions().row(i))
372 "initial != min1: {} of {} atoms past the {} A tolerance "
373 "for min1 ({} for min2); largest separation {} A",
380 QUILL_LOG_DEBUG(
log,
"both minima are the initial state");
384 if (!
params.process_search_options().minimize_first) {
400 if (!
params.prefactor_options().default_value) {
401 fctmp =
min1->getPotentialCalls();
406 if (prefStatus == -1) {
412 if ((pref1 >
params.prefactor_options().max_value) ||
413 (pref1 <
params.prefactor_options().min_value)) {
417 if ((pref2 >
params.prefactor_options().max_value) ||
418 (pref2 <
params.prefactor_options().min_value)) {
433 std::string resultsFilename(
"results.dat");
436 std::ofstream out(resultsFilename, std::ios::binary);
438 out << std::format(
"{} termination_reason\n", status);
439 out << std::format(
"{} termination_reason_text\n",
441 out << std::format(
"{} random_seed\n",
params.main_options().randomSeed);
443 "{} potential_type\n",
444 magic_enum::enum_name<PotType>(
params.potential_options().potential));
445 out << std::format(
"{} total_force_calls\n",
447 out << std::format(
"{} force_calls_minimization\n",
fCallsMin);
448 out << std::format(
"{} force_calls_saddle\n",
fCallsSaddle);
449 out << std::format(
"{:.12e} potential_energy_saddle\n",
450 saddle->getPotentialEnergy());
451 out << std::format(
"{:.12e} potential_energy_reactant\n",
452 min1->getPotentialEnergy());
453 out << std::format(
"{:.12e} potential_energy_product\n",
454 min2->getPotentialEnergy());
455 out << std::format(
"{:.12e} barrier_reactant_to_product\n",
457 out << std::format(
"{:.12e} barrier_product_to_reactant\n",
459 if (
params.saddle_search_options().method ==
"min_mode") {
460 out << std::format(
"{:.12e} displacement_saddle_distance\n",
463 out << std::format(
"{:.12e} displacement_saddle_distance\n", 0.0);
465 if (
params.saddle_search_options().method ==
"dynamics") {
467 out << std::format(
"{:.12e} simulation_time\n",
468 ds.time *
params.constants().timeUnit);
469 out << std::format(
"{:.12e} md_temperature\n",
470 params.saddle_search_options().dynamics.temperature);
473 out << std::format(
"{:.12e} prefactor_reactant_to_product\n",
475 out << std::format(
"{:.12e} prefactor_product_to_reactant\n",
479 std::string reactantFilename(
"reactant.con");
482 QUILL_LOG_ERROR(
log,
"Failed to write {}", reactantFilename);
485 std::string modeFilename(
"mode.dat");
489 std::string saddleFilename(
"saddle.con");
492 QUILL_LOG_ERROR(
log,
"Failed to write {}", saddleFilename);
495 std::string productFilename(
"product.con");
498 QUILL_LOG_ERROR(
log,
"Failed to write {}", productFilename);
505 QUILL_LOG_DEBUG(
log,
"[Saddle Search] {}", msg);
507 QUILL_LOG_ERROR(
log,
"[Saddle Search] {}", msg);
Eigen::Matrix< double, Eigen::Dynamic, 3, eOnStorageOrder > AtomMatrix
#define EONC_LOG_DEBUG(...)
#define EONC_LOG_ERROR(...)
#define EONC_LOG_CRITICAL(...)
The optimizer class is used to serve as an abstract class for all optimizers, as well as to call an o...
Finds possible escape mecahnisms from a state.
std::shared_ptr< Potential > pot
static const char MINMODE_GPRDIMER[]
bool compare(const Matter &matter, bool indistinguishable=false)
@ STATUS_NEGATIVE_BARRIER
@ STATUS_FAILED_PREFACTOR
@ STATUS_BAD_NOT_CONNECTED
@ STATUS_BAD_HIGH_BARRIER
std::shared_ptr< Matter > displacement
Configuration used during the saddle point search.
size_t fCallsPrefactors
Force calls to find the prefactors.
size_t fCallsMin
Force calls to minimize.
std::shared_ptr< Matter > min1
First minimum from the saddle.
std::vector< std::string > returnFiles
Container for the results of the run.
double prefactorsValues[2]
void printEndState(int status)
Logs the run status and makes sure the run was successful.
std::shared_ptr< Matter > min2
Second minimum from the saddle.
std::shared_ptr< Matter > saddle
Configuration used during the saddle point search.
std::vector< std::string > run(void) override
Kicks off the Process Search.
std::shared_ptr< Matter > initial
Initial configuration.
std::unique_ptr< SaddleSearchMethod > saddleSearch
Pulled from parameters.
size_t fCallsSaddle
Force calls to find the saddle.
void saveData(int status)
Writes the results from the run to file.
std::shared_ptr< Matter > runFromMatter(std::shared_ptr< Matter > seed)
In-process entry: seed reactant Matter, no pos.con.
std::shared_ptr< Matter > runPrepared()
int doProcessSearch(void)
Runs the correct saddle search; also checks if the run was successful.
int getPrefactors(const Parameters ¶meters, Matter *min1, Matter *saddle, Matter *min2, double &pref1, double &pref2)
bool applyClientDisplacement(Matter &target, const Matter &initial, const Parameters ¶ms, 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.
std::shared_ptr< Potential > makePotential(const Parameters ¶ms)
constexpr bool io_ok(IoStatus s) noexcept
RAII resource manager for the ARTn C library with global synchronization.
bool potAllowsSharedInstance(const P &p) noexcept