/* * 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 . */ /* * XyzParser.cpp * * Created on: Mar 2, 2010 * Author: metzler */ // include config.h #ifdef HAVE_CONFIG_H #include #endif //#include "CodePatterns/MemDebug.hpp" #include #include #include "CodePatterns/Log.hpp" #include "CodePatterns/Verbose.hpp" #include "XyzParser.hpp" #include "Atom/atom.hpp" #include "Element/element.hpp" #include "Element/periodentafel.hpp" #include "molecule.hpp" #include "World.hpp" using namespace std; // declare specialized static variables const std::string FormatParserTrait::name = "xyz"; const std::string FormatParserTrait::suffix = "xyz"; const ParserTypes FormatParserTrait::type = xyz; /** * Constructor. */ FormatParser< xyz >::FormatParser() : FormatParser_common(NULL), comment("") {} /** * Destructor. */ FormatParser< xyz >::~FormatParser() {} /** * Loads an XYZ file into the World. * * \param XYZ file */ void FormatParser< xyz >::load(istream* file) { atom* newAtom = NULL; molecule* newmol = NULL; int numberOfAtoms; string elementtype; string streambuffer; std::vector AddedAtoms; // create the molecule newmol = World::getInstance().createMolecule(); newmol->ActiveFlag = true; // the first line tells number of atoms, // where we need this construct due to skipping of empty lines below getline(*file, streambuffer); unsigned int step = 0; while (file->good()) { std::stringstream numberstream(streambuffer); numberstream >> numberOfAtoms; if (step == 0) AddedAtoms.resize(numberOfAtoms); // the second line is always a comment getline(*file, streambuffer); comment = streambuffer; LOG(3, "DEBUG: comment is '" << comment << "'."); for (int i = 0; i < numberOfAtoms; i++) { // parse type and position *file >> elementtype; Vector tempVector; for (int j=0;j> tempVector[j]; } LOG(4, "INFO: Parsed type as " << elementtype << " and position at " << tempVector << " for time step " << step); if (step == 0) { newAtom = World::getInstance().createAtom(); newAtom->setType(World::getInstance().getPeriode()->FindElement(elementtype.c_str())); newmol->AddAtom(newAtom); AddedAtoms[i] = newAtom; LOG(5, "INFO: Created new atom, setting " << i << " th component of AddedAtoms."); } else { newAtom = AddedAtoms[i]; LOG(5, "INFO: Using present atom " << *newAtom << " from " << i << " th component of AddedAtoms."); ASSERT(newAtom->getType() == World::getInstance().getPeriode()->FindElement(elementtype.c_str()), "FormatParser< xyz >::load() - atom has different type "+newAtom->getType()->getSymbol()+" than parsed now "+elementtype+", mixed up order?"); } newAtom->setPositionAtStep(step, tempVector); } getline (*file, streambuffer); // eat away rest of last line // skip empty lines unsigned int counter = 0; while (file->good()) { getline (*file, streambuffer); LOG(4, "INFO: Skipped line is '" << streambuffer << "'"); counter++; if (!streambuffer.empty()) break; } LOG(3, "INFO: I skipped "+toString(counter)+" empty lines."); ++step; } BOOST_FOREACH(const atom *_atom, const_cast(World::getInstance()).getAllAtoms()) LOG(3, "INFO: Atom " << _atom->getName() << " " << *dynamic_cast(_atom) << "."); // refresh atom::nr and atom::name newmol->getAtomCount(); } const std::string FormatParser< xyz >::printCoordinate(const double value) { std::stringstream position; if (fabs(value) > 1000) // enforce precision for large components position << std::fixed << std::setprecision(3) << value; else position << value; return position.str(); } /** * Saves the \a atoms into as a XYZ file. * * \param file where to save the state * \param atoms atoms to store */ void FormatParser< xyz >::save( ostream* file, const std::vector &atoms) { LOG(2, "DEBUG: Saving changes to xyz."); // get max and min trajectories std::pair minmax_trajectories = getMinMaxTrajectories(atoms); LOG(2, "INFO: There are " << minmax_trajectories.second << " steps to save."); // always store at least one step for (size_t step = 0; (step < minmax_trajectories.second) || (step == 0); ++step) { if (step != 0) *file << "\n"; //if (comment == "") { time_t now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' comment = "Created by molecuilder on "; // ctime ends in \n\0, we have to cut away the newline std::string time(ctime(&now)); size_t pos = time.find('\n'); if (pos != 0) comment += time.substr(0,pos); else comment += time; comment += ", time step "+toString(step); //} *file << atoms.size() << endl << "\t" << comment << endl; for(vector::const_iterator it = atoms.begin(); it != atoms.end(); it++) { *file << (*it)->getType()->getSymbol(); *file << "\t" << printCoordinate((*it)->atStep(0, step)); *file << "\t" << printCoordinate((*it)->atStep(1, step)); *file << "\t" << printCoordinate((*it)->atStep(2, step)); *file << endl; } } }