diff --git a/src/basics/writer/WbWriterVtkXmlBinary.cpp b/src/basics/writer/WbWriterVtkXmlBinary.cpp
index b2e38c4e5ebdc3651be8688fed674934de106478..bfc35dbe4629e7ecba86f955f1d1e322e8b90e6a 100644
--- a/src/basics/writer/WbWriterVtkXmlBinary.cpp
+++ b/src/basics/writer/WbWriterVtkXmlBinary.cpp
@@ -39,50 +39,78 @@
 
 using namespace std;
 
-/*===============================================================================*/
-const std::string WbWriterVtkXmlBinary::pvdEndTag = "   </Collection>\n</VTKFile>";
-/*===============================================================================*/
-string WbWriterVtkXmlBinary::writeCollection(const string &filename, const vector<string> &filenames,
-                                             const double &timeStep, const bool &sepGroups)
+ofstream createFileStream(const std::string &vtkFilename)
 {
-    string vtkfilename = filename + ".pvd";
-    ofstream out(vtkfilename.c_str());
-    if (!out) {
-        out.clear(); // flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
-        string path = UbSystem::getPathFromString(vtkfilename);
-        if (path.size() > 0) {
+    ofstream outputFileStream(vtkFilename.c_str(), ios::out | ios::binary);
+    if (!outputFileStream) {
+        outputFileStream.clear();
+        const std::string path = UbSystem::getPathFromString(vtkFilename);
+        if (!path.empty()) {
             UbSystem::makeDirectory(path);
-            out.open(vtkfilename.c_str());
+            outputFileStream.open(vtkFilename.c_str(), ios::out | ios::binary);
         }
-        if (!out)
-            throw UbException(UB_EXARGS, "couldn't open file " + vtkfilename);
+        if (!outputFileStream) throw UbException(UB_EXARGS, "couldn't open file " + vtkFilename);
     }
+    return outputFileStream;
+}
 
-    string endian;
-    if (UbSystem::isLittleEndian())
-        endian = "LittleEndian";
-    else
-        endian = "BigEndian";
-    out << "<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"" << endian << "\" >" << endl;
-    out << "   <Collection>" << endl;
+void addCollectionHeader(std::ofstream &outputFileStream)
+{
+    std::string endian = UbSystem::isLittleEndian() ? "LittleEndian" : "BigEndian";
+    outputFileStream << "<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"" << endian << "\" >" << endl;
+    outputFileStream << "   <Collection>" << endl;
+}
 
+void addCollectionDatasetsForTimeStep(std::ofstream &outputFileStream, const vector<string> &filenames, double timeStep, bool separateGroups)
+{
     int group = 0, part = 0;
     for (size_t i = 0; i < filenames.size(); i++) {
-        out << "       <DataSet timestep=\"" << timeStep << "\" group=\"" << group << "\" part=\"" << part
-            << "\" file=\"" << filenames[i] << "\"/>" << endl;
-        if (sepGroups)
+        outputFileStream << "       <DataSet timestep=\"" << timeStep << "\" group=\"" << group << "\" part=\"" << part << "\" file=\"" << filenames[i] << "\"/>" << endl;
+        if (separateGroups)
             group++;
         else
             part++;
     }
-    out << pvdEndTag;
-    out.close();
+}
 
-    return vtkfilename;
+std::string getCollectionEndString()
+{
+    return "   </Collection>\n</VTKFile>";
+}
+
+void finalizeCollectionFile(std::ofstream &outputFileStream)
+{
+    outputFileStream << getCollectionEndString();
+    outputFileStream.close();
+}
+
+std::string WbWriterVtkXmlBinary::writeCollectionForTimeSeries(const std::string &filename,
+                                                               const std::map<uint, std::vector<std::string>> &filesNamesForTimeSteps, bool separateGroups) const
+{
+    std::string vtkFilename = filename + ".pvd";
+    ofstream out = createFileStream(vtkFilename);
+    addCollectionHeader(out);
+    for (auto [timeStep, filenames]: filesNamesForTimeSteps) {
+        addCollectionDatasetsForTimeStep(out, filenames, timeStep, separateGroups);
+    }
+    finalizeCollectionFile(out);
+    return vtkFilename;
 }
+
+string WbWriterVtkXmlBinary::writeCollection(const string &filename, const vector<string> &filenames,
+                                             const double &timeStep, const bool &separateGroups) const
+{
+    std::string vtkFilename = filename + ".pvd";
+    ofstream out = createFileStream(vtkFilename);
+    addCollectionHeader(out);
+    addCollectionDatasetsForTimeStep(out, filenames, timeStep, separateGroups);
+    finalizeCollectionFile(out);
+    return vtkFilename;
+}
+
 /*===============================================================================*/
 string WbWriterVtkXmlBinary::addFilesToCollection(const string &filename, const vector<string> &filenames,
-                                                  const double &timeStep, const bool &sepGroups)
+                                                  const double &timeStep, const bool &separateGroups) const
 {
     string vtkfilename = filename;
     fstream test(vtkfilename.c_str(), ios::in);
@@ -91,41 +119,31 @@ string WbWriterVtkXmlBinary::addFilesToCollection(const string &filename, const
         vtkfilename += ".pvd";
         test.open(vtkfilename.c_str(), ios::in);
         if (!test)
-            return this->writeCollection(filename, filenames, timeStep, sepGroups);
+            return this->writeCollection(filename, filenames, timeStep, separateGroups);
     }
 
     fstream out(vtkfilename.c_str(), ios::in | ios::out);
-    out.seekp(-(int)pvdEndTag.size() - 1, ios_base::end);
+    out.seekp(-(int)getCollectionEndString().size() - 1, ios_base::end);
 
     int group = 0;
     for (size_t i = 0; i < filenames.size(); i++) {
         out << "       <DataSet timestep=\"" << timeStep << "\" group=\"" << group << "\" part=\"" << i << "\" file=\""
             << filenames[i] << "\"/>" << endl;
-        if (sepGroups)
+        if (separateGroups)
             group++;
     }
-    out << pvdEndTag;
+    out <<  getCollectionEndString();
 
     return vtkfilename;
 }
 /*===============================================================================*/
 string WbWriterVtkXmlBinary::writeParallelFile(const string &filename, vector<string> &pieceSources,
-                                               vector<string> &pointDataNames, vector<string> &cellDataNames)
+                                               vector<string> &pointDataNames, vector<string> &cellDataNames) const
 {
     string vtkfilename = filename + ".pvtu";
     UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeParallelFile to " << vtkfilename << " - start");
 
-    ofstream out(vtkfilename.c_str());
-    if (!out) {
-        out.clear(); // flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
-        string path = UbSystem::getPathFromString(vtkfilename);
-        if (path.size() > 0) {
-            UbSystem::makeDirectory(path);
-            out.open(vtkfilename.c_str());
-        }
-        if (!out)
-            throw UbException(UB_EXARGS, "couldn't open file " + vtkfilename);
-    }
+    std::ofstream out = createFileStream(vtkfilename);
 
     // VTK FILE
     out << "<?xml version=\"1.0\"?>\n";
@@ -160,25 +178,6 @@ string WbWriterVtkXmlBinary::writeParallelFile(const string &filename, vector<st
 
 /*===============================================================================*/
 
-// helper functions
-
-ofstream createFileStream(std::string vtkfilename)
-{
-
-    ofstream out(vtkfilename.c_str(), ios::out | ios::binary);
-    if (!out) {
-        out.clear(); // flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
-        string path = UbSystem::getPathFromString(vtkfilename);
-        if (path.size() > 0) {
-            UbSystem::makeDirectory(path);
-            out.open(vtkfilename.c_str(), ios::out | ios::binary);
-        }
-        if (!out)
-            throw UbException(UB_EXARGS, "couldn't open file " + vtkfilename);
-    }
-    return out;
-}
-
 void writeVtkHeader(ofstream &out, int numberOfNodes, int numberOfCells)
 {
     out << "<?xml version=\"1.0\"?>\n";
@@ -286,7 +285,7 @@ void writeCellData(ofstream &out, int bytesPerByteVal, int bytesScalarData, vect
     }
 }
 
-void writeEndOfFile(ofstream &out)
+void writeEndOfVtkFile(ofstream &out)
 {
     out << "\n</AppendedData>\n";
     out << "</VTKFile>";
@@ -323,7 +322,7 @@ string WbWriterVtkXmlBinary::writeLines(const string &filename, vector<UbTupleFl
     writeCellConnectivity(out, bytesPerByteVal, bytesCellConnectivity, lines);
     writeCellOffsets(out, bytesPerByteVal, bytesCellOffsets, nofCells);
     writeCellTypes(out, bytesPerByteVal, bytesCellTypes, nofCells);
-    writeEndOfFile(out);
+    writeEndOfVtkFile(out);
     UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeLines to " << vtkfilename << " - end");
 
     return vtkfilename;
@@ -362,7 +361,7 @@ string WbWriterVtkXmlBinary::writeLinesWithLineData(const string &filename, vect
     writeCellOffsets(out, bytesPerByteVal, bytesCellOffsets, nofCells);
     writeCellTypes(out, bytesPerByteVal, bytesCellTypes, nofCells);
     writeCellData(out, bytesPerByteVal, bytesScalarData, datanames, celldata);
-    writeEndOfFile(out);
+    writeEndOfVtkFile(out);
 
     UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeLinesWithLineData to " << vtkfilename << " - end");
 
@@ -494,17 +493,7 @@ string WbWriterVtkXmlBinary::writeTriangles(const string &filename, vector<UbTup
     string vtkfilename = filename + getFileExtension();
     UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeTriangles to " << vtkfilename << " - start");
 
-    ofstream out(vtkfilename.c_str(), ios::out | ios::binary);
-    if (!out) {
-        out.clear(); // flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
-        string path = UbSystem::getPathFromString(vtkfilename);
-        if (path.size() > 0) {
-            UbSystem::makeDirectory(path);
-            out.open(vtkfilename.c_str(), ios::out | ios::binary);
-        }
-        if (!out)
-            throw UbException(UB_EXARGS, "couldn't open file " + vtkfilename);
-    }
+    ofstream out = createFileStream(vtkfilename);
 
     int nofNodes = (int)nodes.size();
     int nofCells = (int)triangles.size();
@@ -599,17 +588,7 @@ string WbWriterVtkXmlBinary::writeTrianglesWithNodeData(const string &filename,
     string vtkfilename = filename + getFileExtension();
     UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeTrianglesWithNodeData to " << vtkfilename << " - start");
 
-    ofstream out(vtkfilename.c_str(), ios::out | ios::binary);
-    if (!out) {
-        out.clear(); // flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
-        string path = UbSystem::getPathFromString(vtkfilename);
-        if (path.size() > 0) {
-            UbSystem::makeDirectory(path);
-            out.open(vtkfilename.c_str(), ios::out | ios::binary);
-        }
-        if (!out)
-            throw UbException(UB_EXARGS, "couldn't open file " + vtkfilename);
-    }
+    ofstream out = createFileStream(vtkfilename);
 
     int nofNodes = (int)nodes.size();
     int nofCells = (int)cells.size();
@@ -722,17 +701,7 @@ string WbWriterVtkXmlBinary::writeQuads(const string &filename, vector<UbTupleFl
     string vtkfilename = filename + getFileExtension();
     UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeQuads to " << vtkfilename << " - start");
 
-    ofstream out(vtkfilename.c_str(), ios::out | ios::binary);
-    if (!out) {
-        out.clear(); // flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
-        string path = UbSystem::getPathFromString(vtkfilename);
-        if (path.size() > 0) {
-            UbSystem::makeDirectory(path);
-            out.open(vtkfilename.c_str(), ios::out | ios::binary);
-        }
-        if (!out)
-            throw UbException(UB_EXARGS, "couldn't open file " + vtkfilename);
-    }
+    ofstream out = createFileStream(vtkfilename);
 
     int nofNodes = (int)nodes.size();
     int nofCells = (int)cells.size();
@@ -827,17 +796,7 @@ string WbWriterVtkXmlBinary::writeQuadsWithNodeData(const string &filename, vect
     string vtkfilename = filename + getFileExtension();
     UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeQuadsWithNodeData to " << vtkfilename << " - start");
 
-    ofstream out(vtkfilename.c_str(), ios::out | ios::binary);
-    if (!out) {
-        out.clear(); // flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
-        string path = UbSystem::getPathFromString(vtkfilename);
-        if (path.size() > 0) {
-            UbSystem::makeDirectory(path);
-            out.open(vtkfilename.c_str(), ios::out | ios::binary);
-        }
-        if (!out)
-            throw UbException(UB_EXARGS, "couldn't open file " + vtkfilename);
-    }
+    ofstream out = createFileStream(vtkfilename);
 
     int nofNodes = (int)nodes.size();
     int nofCells = (int)cells.size();
@@ -952,17 +911,7 @@ string WbWriterVtkXmlBinary::writeQuadsWithCellData(const string &filename, vect
     string vtkfilename = filename + getFileExtension();
     UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeQuadsWithCellData to " << vtkfilename << " - start");
 
-    ofstream out(vtkfilename.c_str(), ios::out | ios::binary);
-    if (!out) {
-        out.clear(); // flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
-        string path = UbSystem::getPathFromString(vtkfilename);
-        if (path.size() > 0) {
-            UbSystem::makeDirectory(path);
-            out.open(vtkfilename.c_str(), ios::out | ios::binary);
-        }
-        if (!out)
-            throw UbException(UB_EXARGS, "couldn't open file " + vtkfilename);
-    }
+    ofstream out = createFileStream(vtkfilename);
 
     int nofNodes = (int)nodes.size();
     int nofCells = (int)cells.size();
@@ -1081,17 +1030,7 @@ string WbWriterVtkXmlBinary::writeQuadsWithNodeAndCellData(const string &filenam
     string vtkfilename = filename + getFileExtension();
     UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeQuadsWithNodeAndCellData to " << vtkfilename << " - start");
 
-    ofstream out(vtkfilename.c_str(), ios::out | ios::binary);
-    if (!out) {
-        out.clear(); // flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
-        string path = UbSystem::getPathFromString(vtkfilename);
-        if (path.size() > 0) {
-            UbSystem::makeDirectory(path);
-            out.open(vtkfilename.c_str(), ios::out | ios::binary);
-        }
-        if (!out)
-            throw UbException(UB_EXARGS, "couldn't open file " + vtkfilename);
-    }
+    ofstream out = createFileStream(vtkfilename);
 
     int nofNodes = (int)nodes.size();
     int nofCells = (int)cells.size();
@@ -1225,17 +1164,7 @@ string WbWriterVtkXmlBinary::writeOctsWithCellData(const string &filename, vecto
     string vtkfilename = filename + getFileExtension();
     UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeOctsWithCellData to " << vtkfilename << " - start");
 
-    ofstream out(vtkfilename.c_str(), ios::out | ios::binary);
-    if (!out) {
-        out.clear(); // flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
-        string path = UbSystem::getPathFromString(vtkfilename);
-        if (path.size() > 0) {
-            UbSystem::makeDirectory(path);
-            out.open(vtkfilename.c_str(), ios::out | ios::binary);
-        }
-        if (!out)
-            throw UbException(UB_EXARGS, "couldn't open file " + vtkfilename);
-    }
+    ofstream out = createFileStream(vtkfilename);
 
     int nofNodes = (int)nodes.size();
     int nofCells = (int)cells.size();
@@ -1354,17 +1283,7 @@ string WbWriterVtkXmlBinary::writeOctsWithNodeData(const string &filename, vecto
     string vtkfilename = filename + getFileExtension();
     UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeOctsWithNodeData to " << vtkfilename << " - start");
 
-    ofstream out(vtkfilename.c_str(), ios::out | ios::binary);
-    if (!out) {
-        out.clear(); // flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
-        string path = UbSystem::getPathFromString(vtkfilename);
-        if (path.size() > 0) {
-            UbSystem::makeDirectory(path);
-            out.open(vtkfilename.c_str(), ios::out | ios::binary);
-        }
-        if (!out)
-            throw UbException(UB_EXARGS, "couldn't open file " + vtkfilename);
-    }
+    ofstream out = createFileStream(vtkfilename);
 
     int nofNodes = (int)nodes.size();
     int nofCells = (int)cells.size();
@@ -1483,17 +1402,7 @@ string WbWriterVtkXmlBinary::writeOcts(const string &filename, vector<UbTupleFlo
     string vtkfilename = filename + getFileExtension();
     UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeOcts to " << vtkfilename << " - start");
 
-    ofstream out(vtkfilename.c_str(), ios::out | ios::binary);
-    if (!out) {
-        out.clear(); // flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
-        string path = UbSystem::getPathFromString(vtkfilename);
-        if (path.size() > 0) {
-            UbSystem::makeDirectory(path);
-            out.open(vtkfilename.c_str(), ios::out | ios::binary);
-        }
-        if (!out)
-            throw UbException(UB_EXARGS, "couldn't open file " + vtkfilename);
-    }
+    ofstream out = createFileStream(vtkfilename);
 
     int nofNodes = (int)nodes.size();
     int nofCells = (int)cells.size();
@@ -1589,17 +1498,7 @@ std::string WbWriterVtkXmlBinary::writeNodes(const std::string &filename, std::v
     string vtkfilename = filename + getFileExtension();
     UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeNodes to " << vtkfilename << " - start");
 
-    ofstream out(vtkfilename.c_str(), ios::out | ios::binary);
-    if (!out) {
-        out.clear(); // flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
-        string path = UbSystem::getPathFromString(vtkfilename);
-        if (path.size() > 0) {
-            UbSystem::makeDirectory(path);
-            out.open(vtkfilename.c_str(), ios::out | ios::binary);
-        }
-        if (!out)
-            throw UbException(UB_EXARGS, "couldn't open file " + vtkfilename);
-    }
+    ofstream out = createFileStream(vtkfilename);
 
     int nofNodes = (int)nodes.size();
 
@@ -1684,17 +1583,7 @@ std::string WbWriterVtkXmlBinary::writeNodesWithNodeData(const std::string &file
     string vtkfilename = filename + getFileExtension();
     UBLOG(logDEBUG1, "WbWriterVtkXmlBinary::writeNodesWithNodeData to " << vtkfilename << " - start");
 
-    ofstream out(vtkfilename.c_str(), ios::out | ios::binary);
-    if (!out) {
-        out.clear(); // flags ruecksetzen (ansonsten liefert utern if(!out) weiterhin true!!!
-        string path = UbSystem::getPathFromString(vtkfilename);
-        if (path.size() > 0) {
-            UbSystem::makeDirectory(path);
-            out.open(vtkfilename.c_str(), ios::out | ios::binary);
-        }
-        if (!out)
-            throw UbException(UB_EXARGS, "couldn't open file " + vtkfilename);
-    }
+    ofstream out = createFileStream(vtkfilename);
 
     int nofNodes = (int)nodes.size();
 
diff --git a/src/basics/writer/WbWriterVtkXmlBinary.h b/src/basics/writer/WbWriterVtkXmlBinary.h
index 0f2c31eda81ad0c1975c9715ac1b7fb37a06339b..134a544b71e6f3d3036a7424410ed7ad37186a8a 100644
--- a/src/basics/writer/WbWriterVtkXmlBinary.h
+++ b/src/basics/writer/WbWriterVtkXmlBinary.h
@@ -36,6 +36,7 @@
 #include <string>
 
 #include <basics/writer/WbWriter.h>
+#include <basics/DataTypes.h>
 
 #include "basics_export.h"
 
@@ -69,11 +70,13 @@ public:
 
     // write a metafile
     std::string writeCollection(const std::string &filename, const std::vector<std::string> &filenames,
-                                const double &timestep, const bool &sepGroups);
+                                const double &timeStep, const bool &separateGroups) const;
+    std::string writeCollectionForTimeSeries(const std::string &filename,
+                                             const std::map<uint, std::vector<std::string>> &filesNamesForTimeSteps, bool separateGroups) const;
     std::string addFilesToCollection(const std::string &filename, const std::vector<std::string> &filenames,
-                                     const double &timestep, const bool &sepGroups);
+                                     const double &timeStep, const bool &separateGroups) const;
     std::string writeParallelFile(const std::string &filename, std::vector<std::string> &pieceSources,
-                                  std::vector<std::string> &pointDataNames, std::vector<std::string> &cellDataNames);
+                                  std::vector<std::string> &pointDataNames, std::vector<std::string> &cellDataNames) const;
 
     //////////////////////////////////////////////////////////////////////////
     // nodes
diff --git a/src/gpu/VirtualFluids_GPU/Output/FileWriter.cpp b/src/gpu/VirtualFluids_GPU/Output/FileWriter.cpp
index e28c802429c1703314c59402e2d4d490388b8ce1..9d4173b22a458f089d6ba96618dafeb6b89cbca0 100644
--- a/src/gpu/VirtualFluids_GPU/Output/FileWriter.cpp
+++ b/src/gpu/VirtualFluids_GPU/Output/FileWriter.cpp
@@ -54,6 +54,12 @@ std::string makeMedianCollectionFileName(const std::string &prefix, int ID, int
     return prefix + "_bin_median" + makeCollectionFileNameEnding(ID, timestep);
 }
 
+std::string makePvdCollectionFileName(const std::string &prefix, int mpiProcessID)
+{
+    return prefix + "_bin" + "_ID_" + StringUtil::toString<int>(mpiProcessID);
+}
+
+
 void FileWriter::writeInit(std::shared_ptr<Parameter> para, std::shared_ptr<CudaMemoryManager> cudaMemoryManager)
 {
     unsigned int timestep = para->getTimestepInit();
@@ -62,6 +68,7 @@ void FileWriter::writeInit(std::shared_ptr<Parameter> para, std::shared_ptr<Cuda
         writeTimestep(para, timestep, level);
     }
 
+    this->fileNamesForCollectionFileTimeSeries[timestep] = this->fileNamesForCollectionFile;
     this->writeCollectionFile(para, timestep);
 
     if( para->getCalcMedian() )
@@ -73,6 +80,10 @@ void FileWriter::writeTimestep(std::shared_ptr<Parameter> para, unsigned int tim
     for (int level = para->getCoarse(); level <= para->getFine(); level++)
         writeTimestep(para, timestep, level);
 
+    this->fileNamesForCollectionFileTimeSeries[timestep] = this->fileNamesForCollectionFile;
+    if (timestep == para->getTimestepEnd())
+        this->writePvdCollectionFileForTimeSeries(*para);
+
     this->writeCollectionFile(para, timestep);
 
     if( para->getCalcMedian() )
@@ -98,7 +109,6 @@ void FileWriter::writeTimestep(std::shared_ptr<Parameter> para, unsigned int tim
     for(auto fname : fnamesLong)
         this->fileNamesForCollectionFile.push_back(fname.substr( fname.find_last_of('/') + 1 ));
 
-
     if (para->getCalcMedian())
     {
         std::vector<std::string> fnamesMedianLong = writeUnstructuredGridMedianLT(para, level, fnamesMed);
@@ -187,6 +197,12 @@ std::string VIRTUALFLUIDS_GPU_EXPORT FileWriter::writeCollectionFileMedian(std::
     return pFileName;
 }
 
+std::string FileWriter::writePvdCollectionFileForTimeSeries(const Parameter &para)
+{
+    const std::string filename = makePvdCollectionFileName(para.getFName(), para.getMyProcessID());
+    return WbWriterVtkXmlBinary::getInstance()->writeCollectionForTimeSeries(filename, this->fileNamesForCollectionFileTimeSeries, false);
+}
+
 std::vector<std::string> FileWriter::writeUnstructuredGridLT(std::shared_ptr<Parameter> para, int level, std::vector<std::string >& fname)
 {
     std::vector< UbTupleFloat3 > nodes;
diff --git a/src/gpu/VirtualFluids_GPU/Output/FileWriter.h b/src/gpu/VirtualFluids_GPU/Output/FileWriter.h
index 73794f957f573d9dc29f57adff4e15d1f6ba7e18..c30e33b171563a612e224fd08fd1e4ee68b8fea8 100644
--- a/src/gpu/VirtualFluids_GPU/Output/FileWriter.h
+++ b/src/gpu/VirtualFluids_GPU/Output/FileWriter.h
@@ -4,7 +4,7 @@
 #include <memory>
 #include <vector>
 #include <string>
-
+#include <map>
 
 
 #include "DataWriter.h"
@@ -29,10 +29,14 @@ private:
 
     std::string writeCollectionFileMedian( std::shared_ptr<Parameter> para, unsigned int timestep );
 
+    std::string writePvdCollectionFileForTimeSeries(const Parameter &para);
+
     std::vector<std::string> getNodeDataNames(std::shared_ptr<Parameter> para);
     std::vector<std::string> getMedianNodeDataNames(std::shared_ptr<Parameter> para);
 
     std::vector< std::string > fileNamesForCollectionFile;
     std::vector< std::string > fileNamesForCollectionFileMedian;
+
+    std::map<uint, std::vector<std::string>> fileNamesForCollectionFileTimeSeries; // key: timeStep, value: fileNames for timeStep
 };
-#endif
\ No newline at end of file
+#endif
diff --git a/src/gpu/VirtualFluids_GPU/Parameter/Parameter.cpp b/src/gpu/VirtualFluids_GPU/Parameter/Parameter.cpp
index 207debefb76c503bd331d8374556ac2bb46af940..4df626875ad522288325a1a9acd034ca85a56ea3 100644
--- a/src/gpu/VirtualFluids_GPU/Parameter/Parameter.cpp
+++ b/src/gpu/VirtualFluids_GPU/Parameter/Parameter.cpp
@@ -1883,7 +1883,7 @@ std::string Parameter::getOutputPrefix()
 {
     return this->oPrefix;
 }
-std::string Parameter::getFName()
+std::string Parameter::getFName() const
 {
     return this->fname;
 }
@@ -1955,11 +1955,11 @@ int Parameter::getMaxDev()
 {
     return this->maxdev;
 }
-int Parameter::getMyProcessID()
+int Parameter::getMyProcessID() const
 {
     return this->myProcessId;
 }
-int Parameter::getNumprocs()
+int Parameter::getNumprocs() const
 {
     return this->numprocs;
 }
diff --git a/src/gpu/VirtualFluids_GPU/Parameter/Parameter.h b/src/gpu/VirtualFluids_GPU/Parameter/Parameter.h
index ea2511a4f3112cff78c9f65ffd783ec600ba101d..005236788b7670e8a1a8eb5ac021918b11eee86e 100644
--- a/src/gpu/VirtualFluids_GPU/Parameter/Parameter.h
+++ b/src/gpu/VirtualFluids_GPU/Parameter/Parameter.h
@@ -730,11 +730,11 @@ public:
     int getTimeCalcMedEnd();
     int getMaxDev();
     //! \returns the ID of the current MPI process
-    int getMyProcessID();
-    int getNumprocs();
+    int getMyProcessID() const;
+    int getNumprocs() const;
     std::string getOutputPath();
     std::string getOutputPrefix();
-    std::string getFName();
+    std::string getFName() const;
     std::string getGridPath();
     std::string getGeometryFileC();
     std::string getGeometryFileM();