Index: src/Parser/XyzParser.cpp
===================================================================
--- src/Parser/XyzParser.cpp	(revision c6aeb18b62d4b842084aa91283b2e0fb0461c6b1)
+++ src/Parser/XyzParser.cpp	(revision 0180d65014cd485abba4217d46346ac7065712ed)
@@ -49,30 +49,73 @@
  * \param XYZ file
  */
-void XyzParser::load(istream* file) {
+void XyzParser::load(istream* file)
+{
   atom* newAtom = NULL;
   molecule* newmol = NULL;
   int numberOfAtoms;
   char commentBuffer[512], type[3];
-  double tmp;
+  string number;
+  std::list<atom *> AddedAtoms;
 
-  // the first line tells number of atoms, the second line is always a comment
-  *file >> numberOfAtoms >> ws;
-  file->getline(commentBuffer, 512);
-  comment = commentBuffer;
-
+  // create the 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);
-  for (int i = 0; i < numberOfAtoms; i++) {
-    newAtom = World::getInstance().createAtom();
-    *file >> type;
-    for (int j=0;j<NDIM;j++) {
-      *file >> tmp;
-      newAtom->set(j, tmp);
+
+  // the first line tells number of atoms,
+  // where we need this construct due to skipping of empty lines below
+  *file >> number >> ws;
+  unsigned int step = 0;
+  std::list<atom *>::iterator CurrentAtom;
+  do {
+    CurrentAtom = AddedAtoms.begin();
+    std::stringstream numberstream(number);
+    numberstream >> numberOfAtoms;
+    // the second line is always a comment
+    file->getline(commentBuffer, 512);
+    comment = commentBuffer;
+
+    for (int i = 0; i < numberOfAtoms; i++) {
+      // parse type and position
+      *file >> type;
+      Vector tempVector;
+      for (int j=0;j<NDIM;j++) {
+        *file >> tempVector[j];
+      }
+      LOG(4, "INFO: Parsed type as " << type << " and position at "
+          << tempVector << " for time step " << step);
+
+      if (step == 0) {
+        newAtom = World::getInstance().createAtom();
+        newAtom->setType(World::getInstance().getPeriode()->FindElement(type));
+        newmol->AddAtom(newAtom);
+        AddedAtoms.push_back(newAtom);
+        LOG(5, "INFO: Created new atom.");
+      } else {
+        ASSERT(CurrentAtom != AddedAtoms.end(),
+            "XyzParser::load() - not enough added atoms.");
+        newAtom = *CurrentAtom++;
+        ASSERT(newAtom->getType() == World::getInstance().getPeriode()->FindElement(type),
+            "XyzParser::load() - atom has different type, mixed up order?");
+        LOG(5, "INFO: Using present atom " << *newAtom << ".");
+      }
+      newAtom->setPositionAtStep(step, tempVector);
     }
-    newAtom->setType(World::getInstance().getPeriode()->FindElement(type));
-    newmol->AddAtom(newAtom);
-  }
+    getline (*file, number);  // eat away rest of last line
+    // skip empty lines
+    unsigned int counter = 0;
+    while (file->good()) {
+      getline (*file, number);
+      LOG(4, "INFO: Skipped line is '" << number << "'");
+      counter++;
+      if (!number.empty())
+        break;
+    }
+    LOG(3, "INFO: I skipped "+toString(counter)+" empty lines.");
+    ++step;
+  } while (file->good());
+  BOOST_FOREACH(atom *_atom, World::getInstance().getAllAtoms())
+    LOG(3, "INFO: Atom " << _atom->getName() << " " << *dynamic_cast<AtomInfo *>(_atom) << ".");
 }
 
@@ -85,19 +128,45 @@
 void XyzParser::save(ostream* file, const std::vector<atom *> &atoms) {
   DoLog(0) && (Log() << Verbose(0) << "Saving changes to xyz." << std::endl);
-  //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;
-  //}
-  *file << atoms.size() << endl << "\t" << comment << endl;
 
-  for(vector<atom*>::const_iterator it = atoms.begin(); it != atoms.end(); it++) {
-    *file << noshowpoint << (*it)->getType()->getSymbol() << "\t" << (*it)->at(0) << "\t" << (*it)->at(1) << "\t" << (*it)->at(2) << endl;
+  // get max and min trajectories
+  unsigned int min_trajectories = 1;
+  unsigned int max_trajectories = 1;
+  for (std::vector<atom *>::const_iterator iter = atoms.begin();
+      iter != atoms.end();
+      ++iter) {
+    if (max_trajectories < (*iter)->getTrajectorySize())
+      max_trajectories = (*iter)->getTrajectorySize();
+    if ((min_trajectories > (*iter)->getTrajectorySize())
+        && (max_trajectories > (*iter)->getTrajectorySize()))
+      min_trajectories = (*iter)->getTrajectorySize();
+  }
+  ASSERT((min_trajectories == max_trajectories) || (min_trajectories == 1),
+      "XyzParser::save() - not all atoms have same number of trajectories.");
+  LOG(2, "INFO: There are " << max_trajectories << " to save.");
+
+  for (unsigned int step = 0; step < max_trajectories; ++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<atom*>::const_iterator it = atoms.begin(); it != atoms.end(); it++) {
+      *file << noshowpoint << (*it)->getType()->getSymbol();
+      *file << "\t" << (*it)->atStep(0, step);
+      *file << "\t" << (*it)->atStep(1, step);
+      *file << "\t" << (*it)->atStep(2, step);
+      *file << endl;
+    }
   }
 }
Index: src/Parser/unittests/ParserXyzUnitTest.cpp
===================================================================
--- src/Parser/unittests/ParserXyzUnitTest.cpp	(revision c6aeb18b62d4b842084aa91283b2e0fb0461c6b1)
+++ src/Parser/unittests/ParserXyzUnitTest.cpp	(revision 0180d65014cd485abba4217d46346ac7065712ed)
@@ -40,5 +40,21 @@
 CPPUNIT_TEST_SUITE_REGISTRATION( ParserXyzUnitTest );
 
-static string waterXyz = "3\n\tH2O: water molecule\nO\t0\t0\t0\nH\t0.758602\t0\t0.504284\nH\t0.758602\t0\t-0.504284\n";
+static string waterXyz = "\
+3\n\
+\tH2O: water molecule\n\
+O\t0\t0\t0\n\
+H\t0.758602\t0\t0.504284\n\
+H\t0.758602\t0\t-0.504284\n";
+static string waterMultiXyz = "\
+3\n\
+\tH2O: water molecule, time step 0\n\
+O\t0\t0\t0\n\
+H\t0.758602\t0\t0.504284\n\
+H\t0.758602\t0\t-0.504284\n\
+3\n\
+\tH2O: water molecule, time step 1\n\
+O\t0\t0\t0\n\
+H\t0.76\t0\t0.504284\n\
+H\t0.756\t0\t-0.504284\n";
 
 void ParserXyzUnitTest::setUp() {
@@ -95,2 +111,63 @@
   }
 }
+
+void ParserXyzUnitTest::readMultiXyzTest() {
+  cout << "Testing the multi time step XYZ parser." << endl;
+  XyzParser* testParser = new XyzParser();
+  stringstream input;
+  input << waterMultiXyz;
+  testParser->load(&input);
+  input.clear();
+
+  // 3 not 6 atoms!
+  CPPUNIT_ASSERT_EQUAL(3, World::getInstance().numAtoms());
+
+  // check for trajectory size
+  BOOST_FOREACH (atom *_atom, World::getInstance().getAllAtoms())
+    CPPUNIT_ASSERT_EQUAL((size_t) 2, _atom->getTrajectorySize());
+}
+
+void ParserXyzUnitTest::writeMultiXyzTest() {
+  XyzParser* testParser = new XyzParser();
+  stringstream input;
+  input << waterMultiXyz;
+  testParser->load(&input);
+  input.clear();
+
+  // 3 not 6 atoms!
+  CPPUNIT_ASSERT_EQUAL(3, World::getInstance().numAtoms());
+
+  // store and parse in again
+  {
+    stringstream output;
+    std::vector<atom *> atoms = World::getInstance().getAllAtoms();
+    testParser->save(&output, atoms);
+    input << output.str();
+    testParser->load(&input);
+  }
+
+  // now twice as many
+  CPPUNIT_ASSERT_EQUAL(6, World::getInstance().numAtoms());
+
+  // check for trajectory size of all 6! atoms
+  BOOST_FOREACH (atom *_atom, World::getInstance().getAllAtoms())
+    CPPUNIT_ASSERT_EQUAL((size_t) 2, _atom->getTrajectorySize());
+
+  // check every atom
+  std::vector<atom *> atoms = World::getInstance().getAllAtoms();
+  std::vector<atom *>::const_iterator firstiter = atoms.begin();
+  std::vector<atom *>::const_iterator seconditer = atoms.begin();
+  for (size_t i=0;i<3;i++)
+    ++seconditer;
+  for (;
+      seconditer != atoms.end();
+      ++firstiter,++seconditer) {
+    CPPUNIT_ASSERT_EQUAL((*firstiter)->getType(),(*seconditer)->getType());
+    for (unsigned int step = 0; step < 2; ++step) {
+      // check position and type (only stuff xyz stores)
+      CPPUNIT_ASSERT_EQUAL(
+          (*firstiter)->getPositionAtStep(step),
+          (*seconditer)->getPositionAtStep(step));
+    }
+  }
+}
Index: src/Parser/unittests/ParserXyzUnitTest.hpp
===================================================================
--- src/Parser/unittests/ParserXyzUnitTest.hpp	(revision c6aeb18b62d4b842084aa91283b2e0fb0461c6b1)
+++ src/Parser/unittests/ParserXyzUnitTest.hpp	(revision 0180d65014cd485abba4217d46346ac7065712ed)
@@ -21,4 +21,6 @@
   CPPUNIT_TEST_SUITE( ParserXyzUnitTest ) ;
   CPPUNIT_TEST ( rewriteAnXyzTest );
+  CPPUNIT_TEST ( readMultiXyzTest );
+  CPPUNIT_TEST ( writeMultiXyzTest );
   CPPUNIT_TEST_SUITE_END();
 
@@ -28,4 +30,6 @@
 
   void rewriteAnXyzTest();
+  void readMultiXyzTest();
+  void writeMultiXyzTest();
 };
 
Index: tests/regression/Parser/Xyz/post/testmulti.xyz
===================================================================
--- tests/regression/Parser/Xyz/post/testmulti.xyz	(revision 0180d65014cd485abba4217d46346ac7065712ed)
+++ tests/regression/Parser/Xyz/post/testmulti.xyz	(revision 0180d65014cd485abba4217d46346ac7065712ed)
@@ -0,0 +1,19 @@
+2
+	Created by molecuilder on Tue Oct  6 18:34:23 2009, time step 0
+H	10	10	10
+H	11	10	10
+
+2
+	Created by molecuilder on Tue Oct  6 18:34:23 2009, time step 1
+H	10.1	10	10
+H	10.9	10	10
+
+2
+	Created by molecuilder on Tue Oct  6 18:34:23 2009, time step 2
+H	10.2	10	10
+H	10.8	10	10
+
+2
+	Created by molecuilder on Tue Oct  6 18:34:23 2009, time step 3
+H	10.15	10	10
+H	10.85	10	10
Index: tests/regression/Parser/Xyz/pre/testmulti.xyz
===================================================================
--- tests/regression/Parser/Xyz/pre/testmulti.xyz	(revision 0180d65014cd485abba4217d46346ac7065712ed)
+++ tests/regression/Parser/Xyz/pre/testmulti.xyz	(revision 0180d65014cd485abba4217d46346ac7065712ed)
@@ -0,0 +1,20 @@
+2
+	Created by molecuilder on Tue Oct  6 18:34:23 2009, time step 0
+H	10	10	10
+H	11	10	10
+
+2
+	Created by molecuilder on Tue Oct  6 18:34:23 2009, time step 1
+H	10.1	10	10
+H	10.9	10	10
+
+
+2
+	Created by molecuilder on Tue Oct  6 18:34:23 2009, time step 2
+H	10.2	10	10
+H	10.8	10	10
+2
+	Created by molecuilder on Tue Oct  6 18:34:23 2009, time step 3
+H	10.15	10	10
+H	10.85	10	10
+
Index: tests/regression/Parser/Xyz/testsuite-parser-xyz.at
===================================================================
--- tests/regression/Parser/Xyz/testsuite-parser-xyz.at	(revision c6aeb18b62d4b842084aa91283b2e0fb0461c6b1)
+++ tests/regression/Parser/Xyz/testsuite-parser-xyz.at	(revision 0180d65014cd485abba4217d46346ac7065712ed)
@@ -5,4 +5,6 @@
 AT_CHECK([../../molecuilder -i test.xyz -o xyz -l ${abs_top_srcdir}/${AUTOTEST_PATH}/Parser/Xyz/pre/test.xyz], 0, [ignore], [ignore])
 AT_CHECK([file=test.xyz; diff -I '.*Created by molecuilder.*' $file ${abs_top_srcdir}/${AUTOTEST_PATH}/Parser/Xyz/post/$file], 0, [ignore], [ignore])
+AT_CHECK([../../molecuilder -i testmulti.xyz -o xyz -l ${abs_top_srcdir}/${AUTOTEST_PATH}/Parser/Xyz/pre/testmulti.xyz], 0, [ignore], [ignore])
+AT_CHECK([file=testmulti.xyz; diff -I '.*Created by molecuilder.*' $file ${abs_top_srcdir}/${AUTOTEST_PATH}/Parser/Xyz/post/$file], 0, [ignore], [ignore])
 AT_CLEANUP
 
