7 #ifndef READUCT_HESSIANTASK_H_
8 #define READUCT_HESSIANTASK_H_
19 #include <Utils/Properties/Thermochemistry/ThermochemistryCalculator.h>
21 #include "boost/exception/diagnostic_information.hpp"
22 #include <boost/filesystem.hpp>
39 HessianTask(std::vector<std::string>
input, std::vector<std::string>
output, std::shared_ptr<Core::Log> logger =
nullptr)
40 :
Task(std::move(input), std::move(output), std::move(logger)) {
43 std::string
name()
const override {
44 return "Hessian Calculation";
49 observers = {})
const final {
54 bool stopOnError = stopOnErrorExtraction(taskSettings);
55 bool silentCalculator = taskSettings.extract(
"silent_stdout_calculator",
true);
56 if (!taskSettings.empty()) {
57 throw std::logic_error(falseTaskSettingsErrorMessage(
name()));
59 if (observers.size() > 0) {
60 throw std::logic_error(
"HessianTask does not feature algorithm accepting observers, yet one was given");
69 auto calc = copyCalculator(systems, _input.front(),
name());
70 Utils::CalculationRoutines::setLog(*calc,
true,
true, !silentCalculator);
74 if (calc->getStructure()->size() == 1) {
75 throw std::runtime_error(
"Cannot perform Hessian task for monoatomic systems.");
79 if (!calc->results().has<Utils::Property::Hessian>() || !calc->results().has<Utils::Property::Thermochemistry>() ||
80 !calc->results().has<Utils::Property::Energy>()) {
81 calc->setRequiredProperties(Utils::Property::Hessian | Utils::Property::Thermochemistry | Utils::Property::Energy);
83 calc->calculate(
name());
84 if (!calc->results().get<Utils::Property::SuccessfulCalculation>()) {
85 throw std::runtime_error(
name() +
" was not successful");
93 <<
" " +
name() +
" was not successful with error:\n " + boost::current_exception_diagnostic_information()
98 auto hessian = calc->results().get<Utils::Property::Hessian>();
101 auto system = calc->getStructure();
102 Utils::NormalModesContainer modes =
103 Utils::NormalModeAnalysis::calculateNormalModes(hessian, system->getElements(), system->getPositions());
104 auto wavenumbers = modes.getWaveNumbers();
105 auto cout = _logger->output;
106 cout <<
" Vib. Frequencies:\n";
107 cout <<
" [Rot. and trans. vib. removed, imaginary freq. shown as negative.]\n\n";
108 cout.printf(
" %4s %8s\n",
"#",
"cm^-1");
109 for (
unsigned int i = 0; i < wavenumbers.size(); i++) {
110 cout.printf(
" %4d %+8.1f\n", i + 1, wavenumbers[i]);
114 const std::string& outputSystem = (!_output.empty() ? _output[0] : _input[0]);
117 boost::filesystem::path dir(outputSystem);
118 if (wavenumbers[0] < 0.0) {
119 boost::filesystem::create_directory(dir);
122 for (
unsigned int i = 0; i < wavenumbers.size() && wavenumbers[i] < 0.0; ++i) {
123 auto trj = modes.getModeAsMolecularTrajectory(i, *system, 1.0);
124 std::string filename = Utils::format(
"%s.vibmode-%05d.trj.xyz", outputSystem.c_str(), i + 1);
125 std::ofstream xyz((dir / filename).
string(), std::ofstream::out);
131 systems[outputSystem] = calc;
134 auto thermo = calc->results().get<Utils::Property::Thermochemistry>();
135 double temp = calc->settings().getDouble(
"temperature");
136 double pressure = calc->settings().getDouble(
"pressure");
137 cout <<
" Thermochemical Data:\n";
138 cout.printf(
" %35s %+14.9f K\n",
"Temperature (T):", temp);
139 cout.printf(
" %35s %+14.6f Pa\n",
"Pressure (P):", pressure);
140 cout.printf(
" %35s %14d\n",
"Molecular symmetry number:", thermo.overall.symmetryNumber);
141 cout.printf(
" %35s %+14.9f E_h\n",
"Zero Point Vibrational Energy:", thermo.overall.zeroPointVibrationalEnergy);
142 cout.printf(
" %35s %+14.9f E_h/K\n",
"Entropy (S):", thermo.overall.entropy);
143 cout.printf(
" %35s %+14.9f E_h\n",
"Entropy (-TS):", -temp * thermo.overall.entropy);
144 cout.printf(
" %35s %+14.9f E_h\n",
"Enthalpy (H):", thermo.overall.enthalpy);
145 double electronicEnergy = calc->results().get<Utils::Property::Energy>();
146 cout.printf(
" %35s %+14.9f E_h\n",
"Gibbs Energy Correction (dG):", thermo.overall.gibbsFreeEnergy - electronicEnergy);
147 cout.printf(
" %35s %+14.9f E_h\n",
"Electronic Energy (E):", electronicEnergy);
148 cout.printf(
" %35s %+14.9f E_h\n",
"Gibbs Energy (E + dG):", thermo.overall.gibbsFreeEnergy);
158 #endif // READUCT_HESSIANTASK_H_
Definition: HessianTask.h:31
HessianTask(std::vector< std::string > input, std::vector< std::string > output, std::shared_ptr< Core::Log > logger=nullptr)
Construct a new HessianTask.
Definition: HessianTask.h:39
void warningIfMultipleOutputsGiven() const
Warn if more than one output system was specified.
Definition: Task.h:104
static std::ostream & endl(std::ostream &os)
const std::vector< std::string > & input() const
Getter for the expected names of the input systems.
Definition: Task.h:82
static void write(format f, const std::string &fileName, const MolecularTrajectory &m)
bool run(SystemsMap &systems, Utils::UniversalSettings::ValueCollection taskSettings, bool testRunOnly=false, std::vector< std::function< void(const int &, const Utils::AtomCollection &, const Utils::Results &, const std::string &)>> observers={}) const final
Executes the actual task represented by this class.
Definition: HessianTask.h:47
void warningIfMultipleInputsGiven() const
Warn if more than one input system was specified.
Definition: Task.h:95
const std::vector< std::string > & output() const
Getter for the names of the output systems generated by this task.
Definition: Task.h:89
The base class for all tasks in Readuct.
Definition: Task.h:28
std::string name() const override
Getter for the tasks name.
Definition: HessianTask.h:43