27#include <boost/algorithm/string.hpp>
28#include <boost/format.hpp>
54 std::string fileName = options.
get(
"temporary_file").
as<std::string>();
67 std::string& el_file_name) {
77 el_file.open(el_file_name);
78 el_file <<
"$DATA" << endl;
80 for (
const std::string& element_name : UniqueElements) {
82 el_file << elementInfo.
getEleFull(element_name) << endl;
83 for (
const Shell& shell : element) {
89 el_file <<
" " << sh_idx <<
" " <<
indent(gaussian.decay());
90 el_file <<
" " <<
indent(gaussian.contraction());
107 for (
const QMAtom& atom : qmatoms) {
109 inp_file << setw(3) << atom.getElement() << setw(12)
110 << setiosflags(ios::fixed) << setprecision(6) << pos.x()
111 << setw(12) << setiosflags(ios::fixed) << setprecision(6)
112 << pos.y() << setw(12) << setiosflags(ios::fixed)
113 << setprecision(6) << pos.z() << endl;
115 inp_file <<
"* \n" << endl;
133 for (
const std::string& element_name : UniqueElements) {
136 }
catch (std::runtime_error& error) {
138 <<
"No pseudopotential for " << element_name <<
" available" << flush;
145 <<
" " << element_name << endl;
147 <<
" " << element.getNcore() << endl;
152 for (
Index i = 0; i <=
Index(element.getLmax()); i++) {
153 for (
const ECPShell& shell : element) {
154 if (
Index(shell.getL()) == i) {
161 inp_file << sh_idx <<
" " << gaussian.decay_ <<
" "
162 << gaussian.contraction_ <<
" " << gaussian.power_ << endl;
184 std::ofstream crg_file;
185 std::string crg_file_name_full_ =
run_dir_ +
"/background.crg";
186 crg_file.open(crg_file_name_full_);
187 Index total_background = 0;
190 if (site->getCharge() != 0.0) {
196 crg_file << total_background << endl;
197 boost::format fmt(
"%1$+1.7f %2$+1.7f %3$+1.7f %4$+1.7f");
202 boost::str(fmt % site->getCharge() % pos.x() % pos.y() % pos.z());
203 if (site->getCharge() != 0.0) {
204 crg_file << sitestring << endl;
206 std::vector<MinimalMMCharge> split_multipoles =
SplitMultipoles(*site);
207 for (
const auto& mpoles : split_multipoles) {
210 boost::str(fmt % mpoles.q_ % pos2.x() % pos2.y() % pos2.z());
211 crg_file << multipole << endl;
225 std::vector<std::string> results;
226 std::string temp_suffix =
"/id";
228 std::ofstream inp_file;
230 inp_file.open(inp_file_name_full);
232 inp_file <<
"* xyz " <<
charge_ <<
" " <<
spin_ << endl;
239 <<
"nprocs " << threads <<
"\nend"
243 std::string el_file_name =
run_dir_ +
"/" +
"system.bas";
245 inp_file <<
"%basis\n";
246 inp_file <<
"GTOName"
249 <<
"\"system.bas\";" << endl;
251 std::string aux_file_name =
run_dir_ +
"/" +
"system.aux";
252 std::string auxbasisset_name =
255 inp_file <<
"GTOAuxName"
258 <<
"\"system.aux\";" << endl;
274 Eigen::Vector3d field =
options_.
get(
"externalfield").
as<Eigen::Vector3d>();
275 inp_file <<
"%scf\n ";
276 inp_file <<
" efield " << field.x() <<
", " << field.y() <<
", "
277 << field.z() <<
"\n";
279 inp_file << std::endl;
281 std::string input_options;
283 for (
const auto& prop : this->
options_.
get(
"orca")) {
284 const std::string& prop_name = prop.name();
285 if (prop_name ==
"pointcharges") {
287 }
else if (prop_name !=
"method") {
293 inp_file << input_options;
299 <<
"Setting the scratch dir to " <<
scratch_dir_ + temp_suffix << flush;
309 shell_file.open(shell_file_name_full);
310 shell_file <<
"#!/usr/bin/env bash" << endl;
314 if (
options_.
get(
"initial_guess").
as<std::string>() ==
"orbfile") {
315 if (!(std::filesystem::exists(
run_dir_ +
"/molA.gbw") &&
316 std::filesystem::exists(
run_dir_ +
"/molB.gbw"))) {
318 "Using guess relies on a molA.gbw and a molB.gbw file being in the "
322 <<
"_mergefrag molA.gbw molB.gbw " << base_name
323 <<
".gbw > merge.log" << endl;
325 shell_file <<
options_.
get(
"executable").
as<std::string>() <<
" "
328 shell_file <<
options_.
get(
"executable").
as<std::string>() <<
"_2mkl "
329 << base_name <<
" -molden" << endl;
341 if (std::system(
nullptr)) {
344 Index check = std::system(command.c_str());
370 if (
options_.
get(
"initial_guess").
as<std::string>() ==
"orbfile") {
371 remove((
run_dir_ +
"/" +
"molA.gbw").c_str());
372 remove((
run_dir_ +
"/" +
"molB.gbw").c_str());
373 remove((
run_dir_ +
"/" +
"dimer.gbw").c_str());
378 for (
const std::string& substring : tok_cleanup) {
379 if (substring ==
"inp") {
381 remove(file_name.c_str());
384 if (substring ==
"bas") {
385 std::string file_name =
run_dir_ +
"/system.bas";
386 remove(file_name.c_str());
389 if (substring ==
"log") {
391 remove(file_name.c_str());
394 if (substring ==
"gbw") {
396 remove(file_name.c_str());
399 if (substring ==
"ges") {
400 std::string file_name =
run_dir_ +
"/system.ges";
401 remove(file_name.c_str());
403 if (substring ==
"prop") {
404 std::string file_name =
run_dir_ +
"/system.prop";
405 remove(file_name.c_str());
420 std::ifstream input_file(log_file_name_full);
426 std::string::size_type charge_pos = line.find(
"CHELPG Charges");
428 if (charge_pos != std::string::npos) {
433 bool hasAtoms = result.
size() > 0;
434 while (nfields == 4) {
435 Index atom_id = boost::lexical_cast<Index>(row.at(0));
436 std::string atom_type = row.at(1);
437 double atom_charge = boost::lexical_cast<double>(row.at(3));
439 nfields =
Index(row.size());
443 throw std::runtime_error(
444 "Getting charges failed. Mismatch in elemts:" +
450 StaticSite(atom_id, atom_type, Eigen::Vector3d::Zero());
463 bool has_pol =
false;
465 Eigen::Matrix3d pol = Eigen::Matrix3d::Zero();
470 std::string::size_type pol_pos = line.find(
"THE POLARIZABILITY TENSOR");
471 if (pol_pos != std::string::npos) {
477 if (line.find(
"The raw cartesian tensor (atomic units)") ==
479 throw std::runtime_error(
480 "Could not find cartesian polarization tensor");
483 for (
Index i = 0; i < 3; i++) {
485 std::vector<double> values =
487 if (values.size() != 3) {
488 throw std::runtime_error(
"polarization line " + line +
489 " cannot be parsed");
492 row << values[0], values[1], values[2];
500 throw std::runtime_error(
"Could not find polarization in logfile");
506 bool found_success =
false;
519 std::map<Index, double> energies;
520 std::map<Index, double> energies_beta;
522 std::map<Index, double> occupancy;
523 std::map<Index, double> occupancy_beta;
526 std::string orca_version;
527 Index orca_major_version = 0;
530 Index number_of_electrons = 0;
531 Index number_of_electrons_beta = 0;
532 Index number_of_virtuals = 0;
533 Index number_of_virtuals_beta = 0;
535 std::vector<std::string> results;
537 std::ifstream input_file(log_file_name_full);
539 if (input_file.fail()) {
541 <<
"File " << log_file_name_full <<
" not found " << flush;
545 <<
"Reading basic ORCA output from " << log_file_name_full << flush;
558 std::string::size_type version_pos = line.find(
"Program Version");
559 if (version_pos != std::string::npos) {
561 orca_version = results[2];
562 boost::trim(orca_version);
565 orca_major_version = boost::lexical_cast<Index>(results[0]);
567 <<
"ORCA Major Version " << orca_major_version << flush;
570 std::string::size_type energy_pos = line.find(
"FINAL SINGLE");
571 if (energy_pos != std::string::npos) {
573 std::string energy = results[4];
575 orbitals.
setQMEnergy(boost::lexical_cast<double>(energy));
582 std::string::size_type HFX_pos = line.find(
"Fraction HF Exchange ScalHFX");
584 if (HFX_pos != std::string::npos) {
586 double ScaHFX = boost::lexical_cast<double>(results.back());
590 <<
"DFT with " << ScaHFX <<
" of HF exchange!" << flush;
593 std::string::size_type dim_pos = line.find(
"Basis Dimension");
594 if (dim_pos != std::string::npos) {
599 levels = boost::lexical_cast<Index>(dim);
604 std::string::size_type OE_pos = line.find(
"ORBITAL ENERGIES");
605 if (OE_pos != std::string::npos) {
607 number_of_electrons = 0;
612 line.find(
"SPIN UP ORBITALS") == std::string::npos) {
614 "Expected to read an open-shell system but found no spin orbitals");
617 if (line.find(
"E(Eh)") == std::string::npos) {
619 <<
"Warning: Orbital Energies not found in log file" << flush;
621 for (
Index i = 0; i < levels; i++) {
622 if (number_of_virtuals == 10 && orca_major_version > 5) {
626 std::string no = results[0];
628 Index levelnumber = boost::lexical_cast<Index>(no);
629 if (levelnumber != i) {
631 "something weird is going on"
634 std::string oc = results[1];
636 double occ = boost::lexical_cast<double>(oc);
639 if (occ == 2 || occ == 1) {
640 number_of_electrons++;
642 }
else if (occ == 0) {
643 number_of_virtuals++;
646 std::string
e = results[2];
648 energies[i] = boost::lexical_cast<double>(
e);
653 number_of_electrons_beta = 0;
654 number_of_virtuals_beta = 0;
658 for (
Index i = 0; i < levels; i++) {
659 if (number_of_virtuals == 10 && orca_major_version > 5) {
663 std::string no = results[0];
665 Index levelnumber = boost::lexical_cast<Index>(no);
666 if (levelnumber != i) {
668 <<
"Have a look at the orbital energies "
669 "something weird is going on"
672 std::string oc = results[1];
674 double occ = boost::lexical_cast<double>(oc);
677 number_of_electrons_beta++;
678 occupancy_beta[i] = occ;
679 }
else if (occ == 0) {
680 number_of_virtuals_beta++;
681 occupancy_beta[i] = occ;
684 "Encountered spin down orbital with occupancy != 0 or 1");
686 std::string
e = results[2];
688 energies_beta[i] = boost::lexical_cast<double>(
e);
693 std::string::size_type success =
694 line.find(
"* SUCCESS *");
695 if (success != std::string::npos) {
696 found_success =
true;
706 <<
"Alpha electrons: " << number_of_electrons << flush;
707 Index occupied_levels = number_of_electrons;
708 Index unoccupied_levels = levels - occupied_levels;
710 <<
"Occupied Alpha levels: " << occupied_levels << flush;
712 <<
"Unoccupied levels: " << unoccupied_levels << flush;
723 for (
Index i = 0; i < number_of_electrons + number_of_virtuals; i++) {
729 <<
"Beta electrons: " << number_of_electrons_beta << flush;
731 <<
"Occupied Beta levels: " << number_of_electrons_beta << flush;
733 <<
"Unoccupied Beta levels: " << levels - number_of_electrons_beta
739 for (
Index i = 0; i < number_of_electrons_beta + number_of_virtuals_beta;
747 return found_success;
751 std::string::size_type coordinates_pos =
752 line.find(
"CARTESIAN COORDINATES (ANGSTROEM)");
754 using Atom =
typename T::Atom_Type;
756 if (coordinates_pos != std::string::npos) {
758 bool has_QMAtoms = mol.size() > 0;
766 while (nfields == 4) {
767 string atom_type = row.at(0);
768 double x = boost::lexical_cast<double>(row.at(1));
769 double y = boost::lexical_cast<double>(row.at(2));
770 double z = boost::lexical_cast<double>(row.at(3));
772 nfields =
Index(row.size());
773 Eigen::Vector3d pos(x, y, z);
775 if (has_QMAtoms ==
false) {
776 mol.push_back(
Atom(atom_id, atom_type, pos));
778 Atom& pAtom = mol.at(atom_id);
790 if (input_file.fail()) {
799 std::string::size_type error = line.find(
"FATAL ERROR ENCOUNTERED");
800 if (error != std::string::npos) {
802 "look in the log file may help."
807 "mpirun detected that one or more processes exited with non-zero "
809 if (error != std::string::npos) {
811 <<
"ORCA had an mpi problem, maybe your openmpi version is not good."
824 std::vector<double> coefficients;
826 if (basis_size == 0) {
828 "Basis size not set, calculator does not parse log file first");
837 "Basisset names should be set before reading the molden file.");
841 std::string file_name =
run_dir_ +
"/" +
845 std::ifstream molden_file(file_name);
846 if (!molden_file.good()) {
847 throw std::runtime_error(
848 "Could not find the molden input file for the MO coefficients.\nIf you "
849 "have run the orca calculation manually or use data from an old\n"
850 "calculation, make sure that besides the .gbw file a .molden.input is\n"
851 "present. If not, convert the .gbw file to a .molden.input file with\n"
852 "the orca_2mkl tool from orca.\nAn example, if you have a benzene.gbw "
853 "file run:\n orca_2mkl benzene -molden\n");
871 std::stringstream ssnumber;
877 ssnumber << setiosflags(ios::fixed) << setprecision(15) << std::scientific
879 std::string snumber = ssnumber.str();
884 std::stringstream stream;
885 std::string section = key.substr(key.find(
".") + 1);
886 stream <<
"%" << section;
888 stream <<
" " <<
options_.
get(key).
as<std::string>() <<
"\n";
900 std::vector<std::string> words = values.
ToVector();
901 return ((words.size() <= 1) ?
true :
false);
905 std::stringstream stream;
906 std::string opt = (
options_.
get(
"optimize").as<bool>()) ?
"Opt" :
"";
908 std::string user_method =
909 (orca.
exists(
"method")) ? orca.
get(
"method").
as<std::string>() :
"";
910 std::string convergence =
"";
911 if (!orca.
exists(
"scf")) {
919 << user_method <<
"\n";
925 std::map<std::string, std::string> votca_to_orca;
927 votca_to_orca[
"XC_HYB_GGA_XC_B1LYP"] =
"B1LYP";
928 votca_to_orca[
"XC_HYB_GGA_XC_B3LYP"] =
"B3LYP";
929 votca_to_orca[
"XC_HYB_GGA_XC_PBEH"] =
"PBE0";
930 votca_to_orca[
"XC_GGA_C_PBE"] =
"PBE";
931 votca_to_orca[
"XC_GGA_X_PBE"] =
"PBE";
933 std::string votca_functional =
934 options_.
get(
"functional").
as<std::vector<std::string>>()[0];
936 std::string orca_functional;
937 if (votca_to_orca.count(votca_functional)) {
938 orca_functional = votca_to_orca.at(votca_functional);
943 throw std::runtime_error(
944 "Cannot translate " + votca_functional +
945 " to orca functional names. Please add a <" + votca_functional +
946 "> to your orca input options with the functional orca should use.");
948 return orca_functional;
void push_back(const T &atom)
const T & at(Index index) const
std::vector< std::string > FindUniqueElements() const
void setPos(const Eigen::Vector3d &r)
const Element & getElement(std::string element_type) const
void Load(const std::string &name)
Container to hold ECPs for all atoms.
std::vector< std::string > Fill(const ECPBasisSet &bs, QMMolecule &atoms)
void Load(const std::string &name)
const ECPElement & getElement(std::string element_type) const
void parseMoldenFile(const std::string &filename, Orbitals &orbitals) const
void setBasissetInfo(const std::string &basisset_name, const std::string &aux_basisset_name="")
container for molecular orbitals
void setScaHFX(double ScaHFX)
double getDFTTotalEnergy() const
const tools::EigenSystem & MOs_beta() const
void setNumberOfAlphaElectrons(Index electrons)
void setNumberOfBetaElectrons(Index electrons)
void setECPName(const std::string &ECP)
void setXCGrid(std::string grid)
void setNumberOfOccupiedLevels(Index occupied_levels)
Index getBasisSetSize() const
void setQMEnergy(double qmenergy)
const tools::EigenSystem & MOs() const
void setQMpackage(const std::string &qmpackage)
const QMMolecule & QMAtoms() const
void setNumberOfOccupiedLevelsBeta(Index occupied_levels_beta)
void setChargeAndSpin(Index charge, Index spin)
const std::string & getECPName() const
const std::string & getDFTbasisName() const
void SetupDftBasis(std::string basis_name)
void setXCFunctionalName(std::string functionalname)
void GetCoordinates(T &mol, std::string &line, std::ifstream &input_file) const
void WriteCoordinates(std::ofstream &inp_file, const QMMolecule &)
void WriteECP(std::ofstream &inp_file, const QMMolecule &)
void WriteBasisset(const QMMolecule &qmatoms, std::string &bs_name, std::string &el_file_name)
std::string GetOrcaFunctionalName() const
std::string indent(const double &number)
std::string getPackageName() const override
Eigen::Matrix3d GetPolarizability() const override
void WriteChargeOption() override
std::map< std::string, std::string > convergence_map_
std::string CreateInputSection(const std::string &key) const
StaticSegment GetCharges() const override
std::string WriteMethod() const
void WriteBackgroundCharges()
bool ParseLogFile(Orbitals &orbitals) override
void ParseSpecificOptions(const tools::Property &options) final
bool ParseMOsFile(Orbitals &orbitals) override
bool KeywordIsSingleLine(const std::string &key) const
bool WriteInputFile(const Orbitals &orbitals) override
std::string log_file_name_
std::vector< std::string > GetLineAndSplit(std::ifstream &input_file, const std::string separators) const
std::vector< std::unique_ptr< StaticSite > > externalsites_
std::vector< MinimalMMCharge > SplitMultipoles(const StaticSite &site) const
std::string mo_file_name_
std::string basisset_name_
std::string shell_file_name_
std::string input_file_name_
Class to represent Atom/Site in electrostatic.
const std::string & getElement() const
#define XTP_LOG(level, log)
std::string EnumToString(L l)
base class for all analysis tools