From 4bfdf0d6fb41b526afc81b5ea638617971f2ebba Mon Sep 17 00:00:00 2001 From: Andrea Iob Date: Fri, 27 Oct 2023 15:01:03 +0200 Subject: [PATCH] IO/VTK: add support for writing time series --- src/IO/VTK.cpp | 164 +++++++++++++++++++++++++++++++ src/IO/VTK.hpp | 6 ++ src/patchkernel/patch_kernel.cpp | 54 +++++++++- src/patchkernel/patch_kernel.hpp | 5 + 4 files changed, 226 insertions(+), 3 deletions(-) diff --git a/src/IO/VTK.cpp b/src/IO/VTK.cpp index 4b83f218ca..ede4ed74b2 100644 --- a/src/IO/VTK.cpp +++ b/src/IO/VTK.cpp @@ -23,6 +23,8 @@ \*---------------------------------------------------------------------------*/ #include +#include +#include #include #include "VTK.hpp" @@ -692,6 +694,25 @@ void VTK::checkAllFields(){ } +/*! + * Writes entire VTK file (headers and data). + * @param[in] writeMode if writeMode == VTKWriteMode::DEFAULT the default write setting will be used according to setCounter(); + * if writeMode == VTKWriteMode::NO_SERIES no time stamp will be added and the counter will not be increased; + * if writeMode == VTKWriteMode::NO_INCREMENT the output file will have the same time stamp like the previous one ; + * @param[in] time is the time associated with the file + */ +void VTK::write( VTKWriteMode writeMode, double time ){ + + // Write VTK file + write(writeMode); + + // Write time series file + if( writeMode == VTKWriteMode::DEFAULT || writeMode == VTKWriteMode::NO_INCREMENT ){ + writeTimeSeries(time); + } + +} + /*! * Writes entire VTK file (headers and data). * @param[in] writeMode if writeMode == VTKWriteMode::DEFAULT the default write setting will be used according to setCounter(); @@ -741,6 +762,23 @@ void VTK::write( const std::string &name, VTKWriteMode writeMode ){ setName(name) ; write(writeMode) ; setName(oldName) ; +} + +/*! + * Writes entire VTK file (headers and data). + * @param[in] name filename to be set for this output only + * @param[in] writeMode if writeMode == VTKWriteMode::DEFAULT the default write setting will be used according to setCounter(); + * if writeMode == VTKWriteMode::NO_SERIES no time stamp will be added and the counter will not be increased; + * if writeMode == VTKWriteMode::NO_INCREMENT the output file will have the same time stamp like the previous one ; + * @param[in] time is the time associated with the file + */ +void VTK::write( const std::string &name, VTKWriteMode writeMode, double time ){ + + std::string oldName = getName() ; + + setName(name) ; + write(writeMode, time) ; + setName(oldName) ; } @@ -762,6 +800,132 @@ void VTK::writeCollection( const std::string &outputName ) const { writeCollection(outputName, outputName) ; } +/*! + * Writes time series file. + * + * If the file doesn't exists or if this is the first data set of the series + * (i.e., the counter is equal to zero), the time series will be written from + * scratch and will contain only the current data set. Otherwise, the existing + * time series will be inspected and the current data set will be either added + * at the end of the series or will it will replace the entry with the same + * file name it such an entry exists. + * + * \param time is the time associated with the data set + */ +void VTK::writeTimeSeries( double time ) const { + writeTimeSeries(getName(), getName(), time) ; +} + +/*! + * Writes time series file. + * + * If the file doesn't exists or if this is the first data set of the series + * (i.e., the counter is equal to zero), the time series will be written from + * scratch and will contain only the current data set. Otherwise, the existing + * time series will be inspected and the current data set will be either added + * at the end of the series or will it will replace the entry with the same + * file name it such an entry exists. + * + * \param outputName filename to be set for this output only + * \param time is the time associated with the data set + */ +void VTK::writeTimeSeries( const std::string &outputName, double time ) const { + writeTimeSeries(outputName, outputName, time) ; +} + +/*! + * Writes time series file. + * + * If the file doesn't exists or if this is the first data set of the series + * (i.e., the counter is equal to zero), the time series will be written from + * scratch and will contain only the current data set. Otherwise, the existing + * time series will be inspected and the current data set will be either added + * at the end of the series or will it will replace the entry with the same + * file name it such an entry exists. + * + * \param outputName filename to be set for this output only + * \param seriesName series filename to be set for this output only + * \param time is the time associated with the data set + */ +void VTK::writeTimeSeries( const std::string &outputName, const std::string &seriesName, double time ) const { + + // Only one process should write the time series + if (m_rank != 0) { + return; + } + + // Initialize series file handle + FileHandler seriesFileHandler = m_fh ; + seriesFileHandler.setSeries(false) ; + seriesFileHandler.setParallel(false) ; + seriesFileHandler.setName(seriesName) ; + seriesFileHandler.setAppendix("pvd") ; + + // Initialize series + if (!seriesFileHandler.exists() || getCounter() == 0) { + std::fstream emptySeriesFileStream; + emptySeriesFileStream.open( seriesFileHandler.getPath(), std::ios::out | std::ios::trunc ) ; + if (!emptySeriesFileStream.is_open()) { + throw std::runtime_error("Cannot create file \"" + seriesFileHandler.getName() + "\"" + " inside the directory \"" + seriesFileHandler.getDirectory() + "\""); + } + + emptySeriesFileStream << "" << std::endl; + emptySeriesFileStream << "" << std::endl; + emptySeriesFileStream << " " << std::endl; + emptySeriesFileStream << " " << std::endl; + emptySeriesFileStream << "" << std::endl; + emptySeriesFileStream.close(); + } + + // Create updated series + FileHandler dataSetFileHandler; + if (m_procs <= 1) { + dataSetFileHandler = m_fh ; + dataSetFileHandler.setSeries(false) ; + dataSetFileHandler.setParallel(false) ; + dataSetFileHandler.setName(outputName); + } else { + dataSetFileHandler = createCollectionHandler(outputName) ; + } + dataSetFileHandler.setDirectory("."); + + std::string line; + std::stringstream series; + + std::fstream seriesFileStream; + seriesFileStream.open( seriesFileHandler.getPath( ), std::ios::in ) ; + if (!seriesFileStream.is_open()) { + throw std::runtime_error("Cannot read file \"" + seriesFileHandler.getName() + "\"" + " inside the directory \"" + seriesFileHandler.getDirectory() + "\""); + } + + while (std::getline(seriesFileStream, line)) { + bool duplicateEntry = (line.find("file=\"" + dataSetFileHandler.getPath() + "\"") != std::string::npos); + bool collectionEnd = (line.find("") != std::string::npos); + + if (collectionEnd || duplicateEntry) { + series << " " << std::endl; + } + + if (!duplicateEntry) { + series << line << std::endl; + } + } + seriesFileStream.close(); + + // Write updated series + std::ofstream updatedSeriesFileStream; + updatedSeriesFileStream.open( seriesFileHandler.getPath( )) ; + if (!updatedSeriesFileStream.is_open()) { + throw std::runtime_error("Cannot create file \"" + seriesFileHandler.getName() + "\"" + " inside the directory \"" + seriesFileHandler.getDirectory() + "\""); + } + + updatedSeriesFileStream << series.rdbuf(); + updatedSeriesFileStream.close(); +} + /*! * Creates a handler for the collection. * diff --git a/src/IO/VTK.hpp b/src/IO/VTK.hpp index 9993c4f939..de8a0e9473 100644 --- a/src/IO/VTK.hpp +++ b/src/IO/VTK.hpp @@ -374,13 +374,19 @@ class VTK{ virtual void readMetaInformation() = 0 ; void readData() ; + void write( VTKWriteMode writeMode, double time ) ; void write( VTKWriteMode writeMode=VTKWriteMode::DEFAULT ) ; + void write( const std::string &, VTKWriteMode writeMode, double time ) ; void write( const std::string &, VTKWriteMode writeMode=VTKWriteMode::NO_INCREMENT ) ; void writeCollection( ) const ; void writeCollection( const std::string &outputName ) const ; virtual void writeCollection( const std::string &outputName, const std::string &collectionName ) const = 0; + void writeTimeSeries( double time ) const; + void writeTimeSeries( const std::string &outputName, double time ) const ; + void writeTimeSeries( const std::string &outputName, const std::string &seriesName, double time ) const ; + protected: //For Writing virtual void writeMetaInformation() const = 0 ; diff --git a/src/patchkernel/patch_kernel.cpp b/src/patchkernel/patch_kernel.cpp index ea04de3b11..c7b637ee0a 100644 --- a/src/patchkernel/patch_kernel.cpp +++ b/src/patchkernel/patch_kernel.cpp @@ -1173,11 +1173,54 @@ void PatchKernel::write(const std::string &filename, VTKWriteMode mode) } /*! - Writes the patch a filename with the same name of the patch. + Writes the patch to filename specified in input. + + \param filename the filename where the patch will be written to + \param mode is the VTK file mode that will be used for writing the patch + \param time is the current time +*/ +void PatchKernel::write(const std::string &filename, VTKWriteMode mode, double time) +{ + std::string oldFilename = m_vtk.getName(); + + m_vtk.setName(filename); + write(mode, time); + m_vtk.setName(oldFilename); +} + +/*! + Writes the patch to filename specified in input. \param mode is the VTK file mode that will be used for writing the patch */ void PatchKernel::write(VTKWriteMode mode) +{ + _writePrepare(); + + m_vtk.write(mode); + + _writeFinalize(); +} + +/*! + Writes the patch a filename with the same name of the patch. + + \param mode is the VTK file mode that will be used for writing the patch + \param time is the current time +*/ +void PatchKernel::write(VTKWriteMode mode, double time) +{ + _writePrepare(); + + m_vtk.write(mode, time); + + _writeFinalize(); +} + +/*! + Internal function to be called before writing the patch. +*/ +void PatchKernel::_writePrepare() { // Get VTK cell count long vtkCellCount = 0; @@ -1246,9 +1289,14 @@ void PatchKernel::write(VTKWriteMode mode) } m_vtk.setDimensions(vtkCellCount, vtkVertexCount, vtkConnectSize, vtkFaceStreamSize); +} - // Write the mesh - m_vtk.write(mode); +/*! + Internal function to be called after writing the patch. +*/ +void PatchKernel::_writeFinalize() +{ + // Nothing to do } /*! diff --git a/src/patchkernel/patch_kernel.hpp b/src/patchkernel/patch_kernel.hpp index c121c02469..a0ddfa4ad2 100644 --- a/src/patchkernel/patch_kernel.hpp +++ b/src/patchkernel/patch_kernel.hpp @@ -682,7 +682,9 @@ friend class PatchManager; void setVTKWriteTarget(WriteTarget targetCells); const CellConstRange getVTKCellWriteRange() const; void write(VTKWriteMode mode = VTKWriteMode::DEFAULT); + void write(VTKWriteMode mode, double time); void write(const std::string &name, VTKWriteMode mode = VTKWriteMode::DEFAULT); + void write(const std::string &name, VTKWriteMode mode, double time); void flushData(std::fstream &stream, const std::string &name, VTKFormat format) override; @@ -903,6 +905,9 @@ friend class PatchManager; virtual void _findCellEdgeNeighs(long id, int edge, const std::vector *blackList, std::vector *neighs) const; virtual void _findCellVertexNeighs(long id, int vertex, const std::vector *blackList, std::vector *neighs) const; + virtual void _writePrepare(); + virtual void _writeFinalize(); + void setExpert(bool expert); void extractEnvelope(PatchKernel &envelope) const;