From 903c5c51c388dadf1ec8fd9bddbf76fe5e3bdce5 Mon Sep 17 00:00:00 2001 From: David Elsing Date: Mon, 23 Oct 2023 22:34:45 +0200 Subject: [PATCH] Allow for reading imaginary vibrational frequencies in ORCA outputs. They are marked by ***imaginary mode*** after the frequency. Also, abort reading normal modes, the IR or the Raman spectrum if an invalid index was found. Signed-off-by: David Elsing --- avogadro/quantumio/orca.cpp | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/avogadro/quantumio/orca.cpp b/avogadro/quantumio/orca.cpp index 2061ee8bb5..c2f3a35b1d 100644 --- a/avogadro/quantumio/orca.cpp +++ b/avogadro/quantumio/orca.cpp @@ -301,7 +301,11 @@ void ORCAOutput::processLine(std::istream& in, GaussianSet* basis) break; list = Core::split(key, ' '); while (!key.empty()) { - if (list.size() != 3) { + // imaginary frequencies can have an additional comment: + // ***imaginary mode*** + if (list.size() != 3 && + (list.size() != 5 || list[3] != "***imaginary" || + list[4] != "mode***")) { break; } // e.g. 0: 0.00 cm**-1 @@ -331,14 +335,24 @@ void ORCAOutput::processLine(std::istream& in, GaussianSet* basis) if (key.empty()) break; list = Core::split(key, ' '); - vector modeIndex; + vector modeIndex; + bool invalid_index = false; while (!key.empty()) { // first we get a set of column numbers // e.g. 1 2 3 4 5 6 7 8 9 10 modeIndex.clear(); - for (unsigned int i = 0; i < list.size(); i++) { - modeIndex.push_back(Core::lexicalCast(list[i])); + for (const auto& index_str : list) { + auto index = Core::lexicalCast(index_str); + if (index >= m_frequencies.size()) { + invalid_index = true; + break; + } + modeIndex.push_back(index); } + // invalid column index + if (invalid_index) + break; + // now we read the displacements .. there should be 3N lines // x,y,z for each atom getline(in, key); @@ -373,7 +387,11 @@ void ORCAOutput::processLine(std::istream& in, GaussianSet* basis) } // the first entry might be 5 or 6 because of removed rotations / // translations - int index = Core::lexicalCast(list[0]); + auto index = Core::lexicalCast(list[0]); + // invalid index + if (index >= m_frequencies.size()) + break; + double intensity = Core::lexicalCast(list[3]); m_IRintensities[index] = intensity; @@ -396,7 +414,10 @@ void ORCAOutput::processLine(std::istream& in, GaussianSet* basis) } // the first entry might be 5 or 6 because of removed rotations / // translations - int index = Core::lexicalCast(list[0]); + auto index = Core::lexicalCast(list[0]); + // invalid index + if (index >= m_frequencies.size()) + break; if (m_RamanIntensities.size() == 0 && index > 0) { while (m_RamanIntensities.size() < index) { m_RamanIntensities.push_back(0.0);