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";
52 bool stopOnError = stopOnErrorExtraction(taskSettings);
53 bool silentCalculator = taskSettings.extract(
"silent_stdout_calculator",
true);
54 if (!taskSettings.empty()) {
55 throw std::logic_error(falseTaskSettingsErrorMessage(
name()));
64 auto calc = copyCalculator(systems, _input.front(),
name());
65 Utils::CalculationRoutines::setLog(*calc,
true,
true, !silentCalculator);
68 if (calc->getStructure()->size() == 1) {
69 throw std::runtime_error(
"Cannot perform Hessian task for monoatomic systems.");
73 if (!calc->results().has<Utils::Property::Hessian>() || !calc->results().has<Utils::Property::Thermochemistry>() ||
74 !calc->results().has<Utils::Property::Energy>()) {
75 calc->setRequiredProperties(Utils::Property::Hessian | Utils::Property::Thermochemistry | Utils::Property::Energy);
77 calc->calculate(
name());
78 if (!calc->results().get<Utils::Property::SuccessfulCalculation>()) {
79 throw std::runtime_error(
name() +
" was not successful");
87 <<
" " +
name() +
" was not successful with error:\n " + boost::current_exception_diagnostic_information()
92 auto hessian = calc->results().get<Utils::Property::Hessian>();
95 auto system = calc->getStructure();
97 Utils::NormalModeAnalysis::calculateNormalModes(hessian, system->getElements(), system->getPositions());
99 auto cout = _logger->output;
100 cout <<
" Vib. Frequencies:\n";
101 cout <<
" [Rot. and trans. vib. removed, imaginary freq. shown as negative.]\n\n";
102 cout.printf(
" %4s %8s\n",
"#",
"cm^-1");
103 for (
unsigned int i = 0; i < wavenumbers.size(); i++) {
104 cout.printf(
" %4d %+8.1f\n", i + 1, wavenumbers[i]);
108 const std::string& outputSystem = (!_output.empty() ? _output[0] : _input[0]);
111 boost::filesystem::path dir(outputSystem);
112 if (wavenumbers[0] < 0.0) {
113 boost::filesystem::create_directory(dir);
116 for (
unsigned int i = 0; i < wavenumbers.size() && wavenumbers[i] < 0.0; ++i) {
118 std::string filename = Utils::format(
"%s.vibmode-%05d.trj.xyz", outputSystem.c_str(), i + 1);
119 std::ofstream xyz((dir / filename).
string(), std::ofstream::out);
125 systems[outputSystem] = calc;
128 auto thermo = calc->results().get<Utils::Property::Thermochemistry>();
129 double temp = calc->settings().getDouble(
"temperature");
130 cout <<
" Thermochemical Data:\n";
131 cout.printf(
" %35s %+14.9f K\n",
"Temperature (T):", temp);
132 cout.printf(
" %35s %14d\n",
"Molecular symmetry number:", thermo.overall.symmetryNumber);
133 cout.printf(
" %35s %+14.9f E_h\n",
"Zero Point Vibrational Energy:", thermo.overall.zeroPointVibrationalEnergy);
134 cout.printf(
" %35s %+14.9f E_h/K\n",
"Entropy (S):", thermo.overall.entropy);
135 cout.printf(
" %35s %+14.9f E_h\n",
"Entropy (-TS):", -temp * thermo.overall.entropy);
136 cout.printf(
" %35s %+14.9f E_h\n",
"Enthalpy (H):", thermo.overall.enthalpy);
137 double electronicEnergy = calc->results().get<Utils::Property::Energy>();
138 cout.printf(
" %35s %+14.9f E_h\n",
"Gibbs Energy Correction (dG):", thermo.overall.gibbsFreeEnergy - electronicEnergy);
139 cout.printf(
" %35s %+14.9f E_h\n",
"Electronic Energy (E):", electronicEnergy);
140 cout.printf(
" %35s %+14.9f E_h\n",
"Gibbs Energy (E + dG):", thermo.overall.gibbsFreeEnergy);
150 #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:99
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:77
bool run(SystemsMap &systems, Utils::UniversalSettings::ValueCollection taskSettings, bool testRunOnly=false) const final
Executes the actual task represented by this class.
Definition: HessianTask.h:47
static void write(format f, const std::string &fileName, const MolecularTrajectory &m)
std::vector< double > getWaveNumbers() const
void warningIfMultipleInputsGiven() const
Warn if more than one input system was specified.
Definition: Task.h:90
const std::vector< std::string > & output() const
Getter for the names of the output systems generated by this task.
Definition: Task.h:84
MolecularTrajectory getModeAsMolecularTrajectory(int modeIndex, const Utils::AtomCollection &structure, double scalingFactor) const
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