/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2010-2012 University of Bonn. All rights reserved. * Copyright (C) 2013 Frederik Heber. All rights reserved. * * * This file is part of MoleCuilder. * * MoleCuilder is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * MoleCuilder is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MoleCuilder. If not, see . */ /* * MpqcParser.cpp * * Created on: 12.06.2010 * Author: heber */ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include "CodePatterns/MemDebug.hpp" #include "MpqcParser.hpp" #include "MpqcParser_Parameters.hpp" #include "Atom/atom.hpp" #include "CodePatterns/Log.hpp" #include "CodePatterns/toString.hpp" #include "config.hpp" #include "Element/element.hpp" #include "Element/periodentafel.hpp" #include "LinearAlgebra/Vector.hpp" #include "molecule.hpp" #include "Parser/Exceptions.hpp" #include "World.hpp" // declare specialized static variables const std::string FormatParserTrait::name = "mpqc"; const std::string FormatParserTrait::suffix = "in"; const ParserTypes FormatParserTrait::type = mpqc; // a converter we often need ConvertTo FormatParser::Converter; /** Constructor of MpqcParser. * */ FormatParser< mpqc >::FormatParser() : FormatParser_common(new MpqcParser_Parameters()) {} /** Destructor of MpqcParser. * */ FormatParser< mpqc >::~FormatParser() {} /** Load an MPQC config file into the World. * \param *file input stream */ void FormatParser< mpqc >::load(istream *file) { bool MpqcSection = false; bool MoleculeSection = false; bool GeometrySection = false; bool GeometrySection_n = false; bool BasisSection = false; bool AuxBasisSection = false; char line[MAXSTRINGSIZE]; typedef boost::tokenizer > tokenizer; boost::char_separator sep("[]"); boost::char_separator angularsep("<>"); boost::char_separator equalitysep(" ="); boost::char_separator whitesep(" \t"); ConvertTo toDouble; int old_n = -1; // note down the last parsed "n" to ascertain it's ascending molecule *newmol = World::getInstance().createMolecule(); newmol->ActiveFlag = true; while (file->good()) { file->getline(line, MAXSTRINGSIZE-1); std::string linestring(line); if (((linestring.find("atoms") == string::npos) || (linestring.find("geometry") == string::npos)) && (linestring.find("}") != string::npos)) { GeometrySection = false; } if ((linestring.find(")") != string::npos)) { // ends a section which do not overlap MpqcSection = false; MoleculeSection = false; BasisSection = false; AuxBasisSection = false; } if (MoleculeSection) { if (GeometrySection) { // we have an atom // LOG(2, "DEBUG: Full line is '" << linestring << "'."); // separate off [..] part tokenizer tokens(linestring, sep); // split part prior to [..] into tokens std::string prior_part(*tokens.begin()); tokenizer prefixtokens(prior_part, whitesep); tokenizer::iterator tok_iter = prefixtokens.begin(); // LOG(2, "DEBUG: Current tok_iter is " << *tok_iter << "."); if (GeometrySection_n) { ASSERT(tok_iter != prefixtokens.end(), "FormatParser< mpqc >::load() - missing n entry for MoleculeSection in line " +linestring+"!"); // if additional n is given, parse and check but discard eventually int n; std::stringstream whitespacefilter(*tok_iter++); whitespacefilter >> ws >> n; if ((old_n != -1) && ((n-1) != old_n)) ELOG(2, "n index is not simply ascending by one but " << n-old_n << ", specific ids are lost!"); if (old_n >= n) { ELOG(1, "n index is not simply ascending, coordinates might get mixed!"); throw ParserException(); } old_n = n; } ASSERT(tok_iter != prefixtokens.end(), "FormatParser< mpqc >::load() - missing atoms entry for MoleculeSection in line " +linestring+"!"); // LOG(2, "DEBUG: Current tok_iter is " << *tok_iter << "."); std::string element; { std::stringstream whitespacefilter(*tok_iter++); whitespacefilter >> ws >> element; } // split [..] part and parse tok_iter = (++tokens.begin()); ASSERT (tok_iter != tokens.end(), "FormatParser< mpqc >::load() - missing geometry entry for MoleculeSection in line " +linestring+"!"); // LOG(2, "DEBUG: Current tok_iter is " << *tok_iter << "."); std::string vector(*tok_iter); tokenizer vectorcomponents(vector, whitesep); Vector X; // if (vectorcomponents.size() != NDIM) // throw ParserException(); tok_iter = vectorcomponents.begin(); for (int i=0; isetType(World::getInstance().getPeriode()->FindElement(element)); newAtom->setPosition(X); newmol->AddAtom(newAtom); LOG(1, "Adding atom " << *newAtom); } } if (MpqcSection) { if (linestring.find("mole<") != string::npos) { // get theory tokenizer tokens(linestring, angularsep); tokenizer::iterator tok_iter = tokens.begin(); ++tok_iter; ASSERT(tok_iter != tokens.end(), "FormatParser< mpqc >::load() - missing token in brackets<> for mole< in line "+linestring+"!"); std::string value(*tok_iter); std::stringstream linestream("theory = "+value); linestream >> getParams(); } else if (linestring.find("integrals<") != string::npos) { // get theory tokenizer tokens(linestring, angularsep); tokenizer::iterator tok_iter = tokens.begin(); ++tok_iter; ASSERT(tok_iter != tokens.end(), "FormatParser< mpqc >::load() - missing token in brackets<> for integrals< in line "+linestring+"!"); std::string value(*tok_iter); std::stringstream linestream("integration = "+value); linestream >> getParams(); } else if ((linestring.find("molecule") == string::npos) && (linestring.find("basis") == string::npos)){ // molecule and basis must not be parsed in this section tokenizer tokens(linestring, equalitysep); tokenizer::iterator tok_iter = tokens.begin(); ASSERT(tok_iter != tokens.end(), "FormatParser< mpqc >::load() - missing token before '=' for MpqcSection in line "+linestring+"!"); std::stringstream whitespacefilter(*tok_iter); std::string key; whitespacefilter >> ws >> key; if (getParams().haveParameter(key)) { std::stringstream linestream(linestring); linestream >> getParams(); } else { // unknown keys are simply ignored as long as parser is incomplete LOG(2, "INFO: '"+key+"' is unknown and ignored."); } } } if (BasisSection) { tokenizer tokens(linestring, equalitysep); tokenizer::iterator tok_iter = tokens.begin(); ASSERT(tok_iter != tokens.end(), "FormatParser< mpqc >::load() - missing token for BasisSection in line "+linestring+"!"); std::string key(*tok_iter++); ASSERT(tok_iter != tokens.end(), "FormatParser< mpqc >::load() - missing value for BasisSection after key "+key+" in line "+linestring+"!"); std::string value(*tok_iter); tok_iter++; // TODO: use exception instead of ASSERT ASSERT(tok_iter == tokens.end(), "FormatParser< mpqc >::load() - more than (key = value) on line "+linestring+"."); if (key == "name") { std::stringstream linestream("basis = "+value); linestream >> getParams(); } } if (AuxBasisSection) { tokenizer tokens(linestring, equalitysep); tokenizer::iterator tok_iter = tokens.begin(); ASSERT(tok_iter != tokens.end(), "FormatParser< mpqc >::load() - missing token for AuxBasisSection in line "+linestring+"!"); std::string key(*tok_iter++); ASSERT(tok_iter != tokens.end(), "FormatParser< mpqc >::load() - missing value for BasisSection after key "+key+" in line "+linestring+"!"); std::string value(*tok_iter); tok_iter++; // TODO: use exception instead of ASSERT ASSERT(tok_iter == tokens.end(), "FormatParser< mpqc >::load() - more than (key = value) on line "+linestring+"."); if (key == "name") { std::stringstream linestream("aux_basis = "+value); linestream >> getParams(); } } // set some scan flags if (linestring.find("mpqc:") != string::npos) { MpqcSection = true; } if (linestring.find("molecule:") != string::npos) { MoleculeSection = true; } if ((linestring.find("atoms") != string::npos) && (linestring.find("geometry") != string::npos)) { GeometrySection = true; if (linestring.find("n") != string::npos) // neither atoms nor geometry contains a letter n GeometrySection_n = true; } if ((linestring.find("basis:") != string::npos) && ((linestring.find("abasis<") == string::npos))) { BasisSection = true; } if (linestring.find("abasis<") != string::npos) { AuxBasisSection = true; } } // refresh atom::nr and atom::name newmol->getAtomCount(); } void FormatParser< mpqc >::OutputMPQCLine(ostream * const out, const atom &_atom, const Vector *center) const { Vector recentered(_atom.getPosition()); recentered -= *center; *out << "\t\t" << _atom.getType()->getSymbol() << " [ "; { std::stringstream posstream; posstream << std::setprecision(12) << recentered[0] << "\t" << recentered[1] << "\t" << recentered[2]; *out << posstream.str(); } *out << " ]" << std::endl; }; /** Saves all atoms and data into a MPQC config file. * \param *file output stream * \param atoms atoms to store */ void FormatParser< mpqc >::save(ostream *file, const std::vector &atoms) { Vector center; // vector allatoms = const_cast(World::getInstance()). // getAllAtoms(); // calculate center // for (std::vector::const_iterator runner = atoms.begin();runner != atoms.end(); ++runner) // center += (*runner)->getPosition(); // center.Scale(1./(double)atoms.size()); center.Zero(); // first without hessian if (file->fail()) { ELOG(1, "Cannot open mpqc output file."); } else { *file << "% Created by MoleCuilder" << endl; *file << "mpqc: (" << endl; *file << "\tcheckpoint = no" << endl; *file << "\tsavestate = " << getParams().getParameter(MpqcParser_Parameters::savestateParam) << endl; *file << "\tdo_gradient = " << getParams().getParameter(MpqcParser_Parameters::do_gradientParam) << endl; if (Converter(getParams().getParameter(MpqcParser_Parameters::hessianParam))) { *file << "\tfreq: (" << endl; *file << "\t\tmolecule=$:molecule" << endl; *file << "\t)" << endl; } const std::string theory = getParams().getParameter(MpqcParser_Parameters::theoryParam); if (theory == getParams().getTheoryName(MpqcParser_Parameters::CLHF)) { *file << "\tmole<" << getParams().getParameter(MpqcParser_Parameters::theoryParam) << ">: (" << endl; *file << "\t\tmolecule = $:molecule" << endl; *file << "\t\t" << getParams().getParameterName(MpqcParser_Parameters::basisParam) << " = $:basis" << endl; *file << "\t\t" << getParams().getParameterName(MpqcParser_Parameters::maxiterParam) << " = " << getParams().getParameter(MpqcParser_Parameters::maxiterParam)<< endl; *file << "\t\t" << getParams().getParameterName(MpqcParser_Parameters::memoryParam) << " = " << getParams().getParameter(MpqcParser_Parameters::memoryParam) << endl; *file << "\t)" << endl; } else if (theory == getParams().getTheoryName(MpqcParser_Parameters::CLKS)) { *file << "\tmole<" << getParams().getParameter(MpqcParser_Parameters::theoryParam) << ">: (" << endl; *file << "\t\tfunctional:(name=B3LYP)" << endl; *file << "\t\tmolecule = $:molecule" << endl; *file << "\t\t" << getParams().getParameterName(MpqcParser_Parameters::basisParam) << " = $:basis" << endl; *file << "\t\t" << getParams().getParameterName(MpqcParser_Parameters::maxiterParam) << " = " << getParams().getParameter(MpqcParser_Parameters::maxiterParam)<< endl; *file << "\t\t" << getParams().getParameterName(MpqcParser_Parameters::memoryParam) << " = " << getParams().getParameter(MpqcParser_Parameters::memoryParam) << endl; *file << "\t)" << endl; } else if (theory == getParams().getTheoryName(MpqcParser_Parameters::MBPT2)) { *file << "\tmole<" << getParams().getParameter(MpqcParser_Parameters::theoryParam) << ">: (" << endl; *file << "\t\t" << getParams().getParameterName(MpqcParser_Parameters::basisParam) << " = $:basis" << endl; *file << "\t\tmolecule = $:molecule" << endl; *file << "\t\t" << getParams().getParameterName(MpqcParser_Parameters::memoryParam) << " = " << getParams().getParameter(MpqcParser_Parameters::memoryParam) << endl; *file << "\t\treference: (" << endl; *file << "\t\t\t" << getParams().getParameterName(MpqcParser_Parameters::maxiterParam) << " = " << getParams().getParameter(MpqcParser_Parameters::maxiterParam)<< endl; *file << "\t\t\t" << getParams().getParameterName(MpqcParser_Parameters::basisParam) << " = $:basis" << endl; *file << "\t\t\tmolecule = $:molecule" << endl; *file << "\t\t\t" << getParams().getParameterName(MpqcParser_Parameters::memoryParam) << " = " << getParams().getParameter(MpqcParser_Parameters::memoryParam) << endl; *file << "\t\t)" << endl; *file << "\t)" << endl; } else if (theory == getParams().getTheoryName(MpqcParser_Parameters::MBPT2_R12)) { *file << "\tmole<" << getParams().getParameter(MpqcParser_Parameters::theoryParam) << ">: (" << endl; *file << "\t\tmolecule = $:molecule" << endl; *file << "\t\t" << getParams().getParameterName(MpqcParser_Parameters::basisParam) << " = $:basis" << endl; *file << "\t\t" << getParams().getParameterName(MpqcParser_Parameters::aux_basisParam) << " = $:abasis" << endl; *file << "\t\t" << getParams().getParameterName(MpqcParser_Parameters::stdapproxParam) << " = \"" << getParams().getParameter(MpqcParser_Parameters::stdapproxParam) << "\"" << endl; *file << "\t\t" << getParams().getParameterName(MpqcParser_Parameters::nfzcParam) << " = " << getParams().getParameter(MpqcParser_Parameters::nfzcParam) << endl; *file << "\t\t" << getParams().getParameterName(MpqcParser_Parameters::memoryParam) << " = " << getParams().getParameter(MpqcParser_Parameters::memoryParam) << endl; *file << "\t\tintegrals:()" << endl; *file << "\t\treference: (" << endl; *file << "\t\t\tmolecule = $:molecule" << endl; *file << "\t\t\t" << getParams().getParameterName(MpqcParser_Parameters::basisParam) << " = $:basis" << endl; *file << "\t\t\tmaxiter = " << getParams().getParameter(MpqcParser_Parameters::maxiterParam) << endl; *file << "\t\t\tmemory = " << getParams().getParameter(MpqcParser_Parameters::memoryParam) << endl; *file << "\t\t\tintegrals<" << getParams().getParameter(MpqcParser_Parameters::integrationParam) << ">:()" << endl; *file << "\t\t)" << endl; *file << "\t)" << endl; } else { ELOG(0, "Unknown level of theory requested for MPQC output file."); } const std::string jobtype = getParams().getParameter(MpqcParser_Parameters::jobtypeParam); if (jobtype == getParams().getJobtypeName(MpqcParser_Parameters::Optimization)) { *file << "\t% optimizer object for the molecular geometry" << endl; *file << "\topt: (" << endl; *file << "\t\tfunction = $..:mole" << endl; *file << "\t\tupdate: ()" << endl; *file << "\t\tconvergence: (" << endl; *file << "\t\t\tcartesian = yes" << endl; *file << "\t\t\tenergy = $..:..:mole" << endl; *file << "\t\t)" << endl; *file << "\t)" << endl; } *file << ")" << endl; *file << "molecule: (" << endl; *file << "\tunit = " << (World::getInstance().getConfig()->GetIsAngstroem() ? "angstrom" : "bohr" ) << endl; *file << "\t{ atoms geometry } = {" << endl; // output of atoms BOOST_FOREACH(const atom *_atom, atoms) { OutputMPQCLine(file, *_atom, ¢er); } *file << "\t}" << endl; *file << ")" << endl; *file << "basis: (" << endl; *file << "\tname = \"" << getParams().getParameter(MpqcParser_Parameters::basisParam) << "\"" << endl; *file << "\tmolecule = $:molecule" << endl; *file << ")" << endl; if (theory == getParams().getTheoryName(MpqcParser_Parameters::MBPT2_R12)) { *file << "% auxiliary basis set specification" << endl; *file << "\tabasis: (" << endl; *file << "\tname = \"" << getParams().getParameter(MpqcParser_Parameters::aux_basisParam) << "\"" << endl; *file << "\tmolecule = $:molecule" << endl; *file << ")" << endl; } } }