/*
* Project: MoleCuilder
* Description: creates and alters molecular systems
* Copyright (C) 2010-2012 University of Bonn. 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 .
*/
/*
* Psi3Parser.cpp
*
* Created on: Oct 04, 2011
* Author: heber
*/
// include config.h
#ifdef HAVE_CONFIG_H
#include
#endif
#include
#include
#include
#include
#include "CodePatterns/MemDebug.hpp"
#include "Psi3Parser.hpp"
#include "Psi3Parser_Parameters.hpp"
#include "Atom/atom.hpp"
#include "CodePatterns/Log.hpp"
#include "CodePatterns/toString.hpp"
#include "Element/element.hpp"
#include "Element/periodentafel.hpp"
#include "LinearAlgebra/Vector.hpp"
#include "molecule.hpp"
#include "MoleculeListClass.hpp"
#include "World.hpp"
// declare specialized static variables
const std::string FormatParserTrait::name = "psi3";
const std::string FormatParserTrait::suffix = "psi";
const ParserTypes FormatParserTrait::type = psi3;
// a converter we often need
ConvertTo FormatParser::Converter;
/** Constructor of Psi3Parser.
*
*/
FormatParser< psi3 >::FormatParser() :
FormatParser_common(new Psi3Parser_Parameters())
{}
/** Destructor of Psi3Parser.
*
*/
FormatParser< psi3 >::~FormatParser()
{}
/** Load an PSI3 config file into the World.
* \param *file input stream
*/
void FormatParser< psi3 >::load(istream *file)
{
bool Psi3Section = false;
bool GeometrySection = 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;
molecule *newmol = World::getInstance().createMolecule();
newmol->ActiveFlag = true;
// TODO: Remove the insertion into molecule when saving does not depend on them anymore. Also, remove molecule.hpp include
World::getInstance().getMolecules()->insert(newmol);
while (file->good()) {
file->getline(line, MAXSTRINGSIZE-1);
std::string linestring(line);
LOG(3, "INFO: Current line is: " << line);
if ((linestring.find(")") != string::npos) && (linestring.find("(") == string::npos)) {
LOG(3, "INFO: Line contains ')' and no '(' (end of section): " << line);
// ends a section which do not overlap
if (GeometrySection)
GeometrySection = false;
else
Psi3Section = false;
}
if (GeometrySection) { // we have an atom
tokenizer tokens(linestring, sep);
// if (tokens.size() != 2)
// throw Psi3ParseException;
tokenizer::iterator tok_iter = tokens.begin();
ASSERT(tok_iter != tokens.end(),
"FormatParser< psi3 >::load() - missing token for MoleculeSection in line "+linestring+"!");
std::stringstream whitespacefilter(*++tok_iter);
std::string element;
whitespacefilter >> ws >> element;
LOG(2, "INFO: element of atom is " << element);
ASSERT(tok_iter != tokens.end(),
"FormatParser< psi3 >::load() - missing token for MoleculeSection in line "+linestring+"!");
std::string vector = *tok_iter;
tokenizer vectorcomponents(vector, whitesep);
Vector X;
// if (vectorcomponents.size() != NDIM)
// throw Psi3ParseException;
tok_iter = vectorcomponents.begin();
++tok_iter;
for (int i=0; isetType(World::getInstance().getPeriode()->FindElement(element));
newAtom->setPosition(X);
newmol->AddAtom(newAtom);
LOG(1, "Adding atom " << *newAtom);
}
if ((Psi3Section) && (!GeometrySection)) {
if (linestring.find("=") != string::npos) { // get param value
tokenizer tokens(linestring, equalitysep);
tokenizer::iterator tok_iter = tokens.begin();
ASSERT(tok_iter != tokens.end(),
"FormatParser< psi3 >::load() - missing token before '=' for Psi3Section in line "+linestring+"!");
std::stringstream whitespacefilter(*tok_iter);
std::string key;
whitespacefilter >> ws >> key;
//LOG(2, "INFO: key to check is: " << key);
if (getParams().haveParameter(key)) {
//LOG(2, "INFO: Line submitted to parameter is: " << linestring);
std::stringstream linestream(linestring);
linestream >> getParams();
} else { // unknown keys are simply ignored as long as parser is incomplete
LOG(3, "INFO: '"+key+"' is unknown and ignored.");
}
}
}
if ((linestring.find("geometry") != string::npos) && (linestring.find("(") != string::npos)) {
LOG(3, "INFO: Line contains geometry and '(': " << line);
GeometrySection = true;
}
if ((linestring.find("psi:") != string::npos) && (linestring.find("(") != string::npos)) {
LOG(3, "INFO: Line contains psi: and '(': " << line);
Psi3Section = true;
}
}
// refresh atom::nr and atom::name
newmol->getAtomCount();
}
void FormatParser< psi3 >::OutputPsi3Line(ostream * const out, const atom &_atom, const Vector *center) const
{
Vector recentered(_atom.getPosition());
recentered -= *center;
*out << "\t( " << _atom.getType()->getSymbol() << "\t" << recentered[0] << "\t" << recentered[1] << "\t" << recentered[2] << " )" << endl;
};
/** Saves all atoms and data into a PSI3 config file.
* \param *file output stream
* \param atoms atoms to store
*/
void FormatParser< psi3 >::save(ostream *file, const std::vector &atoms)
{
Vector center;
// vector allatoms = 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());
// first without hessian
if (file->fail()) {
ELOG(1, "Cannot open psi3 output file.");
} else {
*file << "% Created by MoleCuilder" << std::endl;
*file << "psi: (" << std::endl;
*file << "\t" << getParams().getParameterName(Psi3Parser_Parameters::labelParam)
<< " = \"" << getParams().getParameter(Psi3Parser_Parameters::labelParam) << "\"" << std::endl;
*file << "\t" << getParams().getParameterName(Psi3Parser_Parameters::jobtypeParam)
<< " = " << getParams().getParameter(Psi3Parser_Parameters::jobtypeParam) << std::endl;
*file << "\t" << getParams().getParameterName(Psi3Parser_Parameters::wavefunctionParam)
<< " = " << getParams().getParameter(Psi3Parser_Parameters::wavefunctionParam) << std::endl;
*file << "\t" << getParams().getParameterName(Psi3Parser_Parameters::maxiterParam)
<< " = " << getParams().getParameter(Psi3Parser_Parameters::maxiterParam) << std::endl;
*file << "\t" << getParams().getParameterName(Psi3Parser_Parameters::referenceParam)
<< " = " << getParams().getParameter(Psi3Parser_Parameters::referenceParam) << std::endl;
*file << "\t" << getParams().getParameterName(Psi3Parser_Parameters::basisParam)
<< " = \"" << getParams().getParameter(Psi3Parser_Parameters::basisParam) << "\"" << std::endl;
const std::string reference = getParams().getParameter(Psi3Parser_Parameters::referenceParam);
// if (reference == getParams().getReferenceName(Psi3Parser_Parameters::RHF)) {
// }
// if (reference == getParams().getReferenceName(Psi3Parser_Parameters::ROHF)) {
// }
if ((reference == getParams().getReferenceName(Psi3Parser_Parameters::UHF))
|| (reference == getParams().getReferenceName(Psi3Parser_Parameters::TWOCON))) {
*file << "\t" << getParams().getParameterName(Psi3Parser_Parameters::multiplicityParam)
<< " = " << getParams().getParameter(Psi3Parser_Parameters::multiplicityParam) << std::endl;
*file << "\t" << getParams().getParameterName(Psi3Parser_Parameters::chargeParam)
<< " = " << getParams().getParameter(Psi3Parser_Parameters::chargeParam) << std::endl;
}
if (reference == getParams().getReferenceName(Psi3Parser_Parameters::TWOCON)) {
*file << "\t" << getParams().getParameterName(Psi3Parser_Parameters::soccParam)
<< " = " << getParams().getParameter(Psi3Parser_Parameters::soccParam) << std::endl;
*file << "\t" << getParams().getParameterName(Psi3Parser_Parameters::doccParam)
<< " = " << getParams().getParameter(Psi3Parser_Parameters::doccParam) << std::endl;
*file << "\t" << getParams().getParameterName(Psi3Parser_Parameters::subgroupParam)
<< " = " << getParams().getParameter(Psi3Parser_Parameters::subgroupParam) << std::endl;
*file << "\t" << getParams().getParameterName(Psi3Parser_Parameters::unique_axisParam)
<< " = " << getParams().getParameter(Psi3Parser_Parameters::unique_axisParam) << std::endl;
}
if ((reference != getParams().getReferenceName(Psi3Parser_Parameters::RHF))
&& (reference != getParams().getReferenceName(Psi3Parser_Parameters::ROHF))
&& (reference != getParams().getReferenceName(Psi3Parser_Parameters::UHF))
&& (reference != getParams().getReferenceName(Psi3Parser_Parameters::TWOCON)))
{
ELOG(0, "Unknown level of reference requested for Psi3 output file.");
}
*file << "\t" << getParams().getParameterName(Psi3Parser_Parameters::freeze_coreParam)
<< " = " << getParams().getParameter(Psi3Parser_Parameters::freeze_coreParam) << std::endl;
*file << "\t" << getParams().getParameterName(Psi3Parser_Parameters::unitsParam)
<< " = " << getParams().getParameter(Psi3Parser_Parameters::unitsParam) << std::endl;
*file << "\tgeometry = (" << std::endl;
// output of atoms
BOOST_FOREACH(const atom *_atom, atoms) {
OutputPsi3Line(file, *_atom, ¢er);
}
*file << "\t)" << std::endl;
*file << "\t" << getParams().getParameterName(Psi3Parser_Parameters::originParam)
<< " = " << getParams().getParameter(Psi3Parser_Parameters::originParam) << std::endl;
*file << ")" << std::endl;
}
}