30 auto reactant = std::make_unique<Matter>(
pot,
params);
34 throw std::runtime_error(
"failed to load " + posFile);
38 constexpr std::array<double, 9> dRs = {1e-7, 1e-6, 1e-5, 1e-4, 1e-3,
39 5e-3, 0.01, 0.05, 0.1};
43 const double cutoff =
params.structure_comparison_options().neighbor_cutoff;
47 displacement.resize(reactant->numberOfAtoms(), 3);
48 displacement.setZero();
49 std::string displaced;
50 for (
int i = 0; i < reactant->numberOfAtoms(); i++) {
51 if (reactant->distance(epicenter, i) <= cutoff) {
54 if (!displaced.empty()) {
55 displaced.push_back(
' ');
57 displaced += std::to_string(i);
58 for (
int j = 0; j < 3; j++) {
59 if (reactant->getFixed(i, j)) {
67 const double dispNorm = displacement.norm();
68 if (!(dispNorm > 0.0)) {
69 throw std::runtime_error(
70 "FiniteDifferenceJob: no free atoms in the epicenter neighborhood");
72 displacement /= dispNorm;
77 env.job_type =
"finite_difference";
79 std::ofstream table(
"curvature.dat");
80 table << std::format(
"{:>14s} {:>14s}\n",
"dR",
"curvature");
84 double curvature = 0.0;
85 for (
size_t dRi = 0; dRi < dRs.size(); ++dRi) {
86 posB = posA + displacement * dRs[dRi];
87 reactant->setPositions(posB);
88 forceB = reactant->getForces();
89 curvature =
matDot(forceB - forceA, displacement) / dRs[dRi];
90 table << std::format(
"{:14.8f} {:14.8f}\n", dRs[dRi], curvature);
91 env.extras.emplace_back(std::format(
"dR_{}", dRi), dRs[dRi]);
92 env.extras.emplace_back(std::format(
"curvature_{}", dRi), curvature);
98 env.writeResultsDat(
"results.dat");
99 std::vector<std::string> returnFiles;
100 returnFiles.push_back(
"results.dat");
101 returnFiles.push_back(
"curvature.dat");