From d9ec743c96c943a38d7c598e12a03584914f76b9 Mon Sep 17 00:00:00 2001 From: Stephane Del Pino <stephane.delpino44@gmail.com> Date: Sat, 16 Jul 2022 09:51:24 +0200 Subject: [PATCH] Prepare writers without time specifier Related to #27 --- src/output/GnuplotWriter.cpp | 24 +++++----- src/output/GnuplotWriter.hpp | 12 ++--- src/output/GnuplotWriter1D.cpp | 24 ++++++---- src/output/GnuplotWriter1D.hpp | 12 ++--- src/output/VTKWriter.cpp | 40 ++++++++++------- src/output/VTKWriter.hpp | 12 ++--- src/output/WriterBase.cpp | 45 +++++++++---------- src/output/WriterBase.hpp | 82 +++++++++++++++++++++++++++++++--- 8 files changed, 171 insertions(+), 80 deletions(-) diff --git a/src/output/GnuplotWriter.cpp b/src/output/GnuplotWriter.cpp index cf85b52eb..4f98d0f23 100644 --- a/src/output/GnuplotWriter.cpp +++ b/src/output/GnuplotWriter.cpp @@ -36,7 +36,10 @@ GnuplotWriter::_getFilename() const { std::ostringstream sout; sout << m_base_filename; - sout << '.' << std::setfill('0') << std::setw(4) << m_saved_times.size() << ".gnu"; + if (m_period_manager.has_value()) { + sout << '.' << std::setfill('0') << std::setw(4) << m_period_manager->nbSavedTimes(); + } + sout << ".gnu"; return sout.str(); } @@ -236,9 +239,9 @@ GnuplotWriter::_writeNodeData(const NodeArray<DataType>& node_array, NodeId node template <typename MeshType> void -GnuplotWriter::_write(const std::shared_ptr<const MeshType>& mesh, - const OutputNamedItemDataSet& output_named_item_data_set, - double time) const +GnuplotWriter::_writeAtTime(const std::shared_ptr<const MeshType>& mesh, + const OutputNamedItemDataSet& output_named_item_data_set, + double time) const { if (parallel::rank() == 0) { std::ofstream fout{_getFilename()}; @@ -270,11 +273,11 @@ GnuplotWriter::writeMesh(const std::shared_ptr<const IMesh>& p_mesh) const switch (p_mesh->dimension()) { case 1: { - this->_write(std::dynamic_pointer_cast<const Mesh<Connectivity<1>>>(p_mesh), output_named_item_data_set, 0); + this->_writeAtTime(std::dynamic_pointer_cast<const Mesh<Connectivity<1>>>(p_mesh), output_named_item_data_set, 0); break; } case 2: { - this->_write(std::dynamic_pointer_cast<const Mesh<Connectivity<2>>>(p_mesh), output_named_item_data_set, 0); + this->_writeAtTime(std::dynamic_pointer_cast<const Mesh<Connectivity<2>>>(p_mesh), output_named_item_data_set, 0); break; } default: { @@ -284,8 +287,9 @@ GnuplotWriter::writeMesh(const std::shared_ptr<const IMesh>& p_mesh) const } void -GnuplotWriter::write(const std::vector<std::shared_ptr<const NamedDiscreteFunction>>& named_discrete_function_list, - double time) const +GnuplotWriter::_writeAtTime( + const std::vector<std::shared_ptr<const NamedDiscreteFunction>>& named_discrete_function_list, + double time) const { std::shared_ptr mesh = this->_getMesh(named_discrete_function_list); @@ -293,11 +297,11 @@ GnuplotWriter::write(const std::vector<std::shared_ptr<const NamedDiscreteFuncti switch (mesh->dimension()) { case 1: { - this->_write(std::dynamic_pointer_cast<const Mesh<Connectivity<1>>>(mesh), output_named_item_data_set, time); + this->_writeAtTime(std::dynamic_pointer_cast<const Mesh<Connectivity<1>>>(mesh), output_named_item_data_set, time); break; } case 2: { - this->_write(std::dynamic_pointer_cast<const Mesh<Connectivity<2>>>(mesh), output_named_item_data_set, time); + this->_writeAtTime(std::dynamic_pointer_cast<const Mesh<Connectivity<2>>>(mesh), output_named_item_data_set, time); break; } default: { diff --git a/src/output/GnuplotWriter.hpp b/src/output/GnuplotWriter.hpp index 608d83015..312e4886c 100644 --- a/src/output/GnuplotWriter.hpp +++ b/src/output/GnuplotWriter.hpp @@ -45,16 +45,16 @@ class GnuplotWriter : public WriterBase std::ostream& fout) const; template <typename MeshType> - void _write(const std::shared_ptr<const MeshType>& mesh, - const OutputNamedItemDataSet& output_named_item_data_set, - double time) const; + void _writeAtTime(const std::shared_ptr<const MeshType>& mesh, + const OutputNamedItemDataSet& output_named_item_data_set, + double time) const; + + void _writeAtTime(const std::vector<std::shared_ptr<const NamedDiscreteFunction>>& named_discrete_function_list, + double time) const final; public: void writeMesh(const std::shared_ptr<const IMesh>& mesh) const final; - void write(const std::vector<std::shared_ptr<const NamedDiscreteFunction>>& named_discrete_function_list, - double time) const final; - GnuplotWriter(const std::string& base_filename, const double time_period) : WriterBase(base_filename, time_period) {} ~GnuplotWriter() = default; diff --git a/src/output/GnuplotWriter1D.cpp b/src/output/GnuplotWriter1D.cpp index 65bb4039a..7fbd6612a 100644 --- a/src/output/GnuplotWriter1D.cpp +++ b/src/output/GnuplotWriter1D.cpp @@ -36,7 +36,10 @@ GnuplotWriter1D::_getFilename() const { std::ostringstream sout; sout << m_base_filename; - sout << '.' << std::setfill('0') << std::setw(4) << m_saved_times.size() << ".gnu"; + if (m_period_manager.has_value()) { + sout << '.' << std::setfill('0') << std::setw(4) << m_period_manager->nbSavedTimes(); + } + sout << ".gnu"; return sout.str(); } @@ -257,9 +260,9 @@ GnuplotWriter1D::_writeItemDatas(const std::shared_ptr<const MeshType>& mesh, template <typename MeshType> void -GnuplotWriter1D::_write(const std::shared_ptr<const MeshType>& mesh, - const OutputNamedItemDataSet& output_named_item_data_set, - double time) const +GnuplotWriter1D::_writeAtTime(const std::shared_ptr<const MeshType>& mesh, + const OutputNamedItemDataSet& output_named_item_data_set, + double time) const { bool has_cell_data = false; for (const auto& [name, item_data_variant] : output_named_item_data_set) { @@ -298,12 +301,17 @@ GnuplotWriter1D::_write(const std::shared_ptr<const MeshType>& mesh, void GnuplotWriter1D::writeMesh(const std::shared_ptr<const IMesh>&) const { - throw UnexpectedError("This function should not be called"); + std::ostringstream errorMsg; + errorMsg << "gnuplot_1d_writer does not write meshes\n" + << rang::style::bold << "note:" << rang::style::reset << " one can use " << rang::fgB::blue + << "gnuplot_writer" << rang::fg::reset << " instead"; + throw NormalError(errorMsg.str()); } void -GnuplotWriter1D::write(const std::vector<std::shared_ptr<const NamedDiscreteFunction>>& named_discrete_function_list, - double time) const +GnuplotWriter1D::_writeAtTime( + const std::vector<std::shared_ptr<const NamedDiscreteFunction>>& named_discrete_function_list, + double time) const { std::shared_ptr mesh = this->_getMesh(named_discrete_function_list); @@ -311,7 +319,7 @@ GnuplotWriter1D::write(const std::vector<std::shared_ptr<const NamedDiscreteFunc switch (mesh->dimension()) { case 1: { - this->_write(std::dynamic_pointer_cast<const Mesh<Connectivity<1>>>(mesh), output_named_item_data_set, time); + this->_writeAtTime(std::dynamic_pointer_cast<const Mesh<Connectivity<1>>>(mesh), output_named_item_data_set, time); break; } case 2: { diff --git a/src/output/GnuplotWriter1D.hpp b/src/output/GnuplotWriter1D.hpp index b003d1756..f1e7b23c8 100644 --- a/src/output/GnuplotWriter1D.hpp +++ b/src/output/GnuplotWriter1D.hpp @@ -38,16 +38,16 @@ class GnuplotWriter1D : public WriterBase void _writePreamble(const OutputNamedItemDataSet& output_named_item_value_set, std::ostream& fout) const; template <typename MeshType> - void _write(const std::shared_ptr<const MeshType>& mesh, - const OutputNamedItemDataSet& output_named_item_value_set, - double time) const; + void _writeAtTime(const std::shared_ptr<const MeshType>& mesh, + const OutputNamedItemDataSet& output_named_item_value_set, + double time) const; + + void _writeAtTime(const std::vector<std::shared_ptr<const NamedDiscreteFunction>>& named_discrete_function_list, + double time) const final; public: void writeMesh(const std::shared_ptr<const IMesh>& mesh) const final; - void write(const std::vector<std::shared_ptr<const NamedDiscreteFunction>>& named_discrete_function_list, - double time) const final; - GnuplotWriter1D(const std::string& base_filename, const double time_period) : WriterBase(base_filename, time_period) {} diff --git a/src/output/VTKWriter.cpp b/src/output/VTKWriter.cpp index de7be9f66..55a2e90d9 100644 --- a/src/output/VTKWriter.cpp +++ b/src/output/VTKWriter.cpp @@ -130,7 +130,10 @@ VTKWriter::_getFilenamePVTU() const { std::ostringstream sout; sout << m_base_filename; - sout << '.' << std::setfill('0') << std::setw(4) << m_saved_times.size() << ".pvtu"; + if (m_period_manager.has_value()) { + sout << '.' << std::setfill('0') << std::setw(4) << m_period_manager->nbSavedTimes(); + } + sout << ".pvtu"; return sout.str(); } @@ -158,7 +161,10 @@ VTKWriter::_getFilenameVTU(int rank_number) const if (parallel::size() > 1) { sout << '-' << std::setfill('0') << std::setw(4) << rank_number; } - sout << '.' << std::setfill('0') << std::setw(4) << m_saved_times.size() << ".vtu"; + if (m_period_manager.has_value()) { + sout << '.' << std::setfill('0') << std::setw(4) << m_period_manager->nbSavedTimes(); + } + sout << ".vtu"; return sout.str(); } @@ -349,10 +355,14 @@ VTKWriter::_write_node_data(std::ofstream& os, template <typename MeshType> void -VTKWriter::_write(const std::shared_ptr<const MeshType>& mesh, - const OutputNamedItemDataSet& given_output_named_item_data_set, - double time) const +VTKWriter::_writeAtTime(const std::shared_ptr<const MeshType>& mesh, + const OutputNamedItemDataSet& given_output_named_item_data_set, + double time) const { + if (not m_period_manager.has_value()) { + throw NormalError("Writer has no period defined"); + } + OutputNamedItemDataSet output_named_item_data_set{given_output_named_item_data_set}; // Adding basic mesh information output_named_item_data_set.add(NamedItemData{"cell_number", mesh->connectivity().cellNumber()}); @@ -612,12 +622,12 @@ VTKWriter::_write(const std::shared_ptr<const MeshType>& mesh, fout << "<VTKFile type=\"Collection\" version=\"0.1\">\n"; fout << "<Collection>\n"; - for (size_t i_time = 0; i_time < m_saved_times.size(); ++i_time) { + for (size_t i_time = 0; i_time < m_period_manager->nbSavedTimes(); ++i_time) { std::ostringstream sout; sout << m_base_filename; sout << '.' << std::setfill('0') << std::setw(4) << i_time << ".pvtu"; - fout << "<DataSet timestep=\"" << m_saved_times[i_time] << "\" file=\"" << sout.str() << "\"/>\n"; + fout << "<DataSet timestep=\"" << m_period_manager->savedTime(i_time) << "\" file=\"" << sout.str() << "\"/>\n"; } fout << "<DataSet timestep=\"" << time << "\" file=\"" << _getFilenamePVTU() << "\"/>\n"; @@ -633,15 +643,15 @@ VTKWriter::writeMesh(const std::shared_ptr<const IMesh>& mesh) const switch (mesh->dimension()) { case 1: { - this->_write(std::dynamic_pointer_cast<const Mesh<Connectivity<1>>>(mesh), output_named_item_data_set, 0); + this->_writeAtTime(std::dynamic_pointer_cast<const Mesh<Connectivity<1>>>(mesh), output_named_item_data_set, 0); break; } case 2: { - this->_write(std::dynamic_pointer_cast<const Mesh<Connectivity<2>>>(mesh), output_named_item_data_set, 0); + this->_writeAtTime(std::dynamic_pointer_cast<const Mesh<Connectivity<2>>>(mesh), output_named_item_data_set, 0); break; } case 3: { - this->_write(std::dynamic_pointer_cast<const Mesh<Connectivity<3>>>(mesh), output_named_item_data_set, 0); + this->_writeAtTime(std::dynamic_pointer_cast<const Mesh<Connectivity<3>>>(mesh), output_named_item_data_set, 0); break; } default: { @@ -651,8 +661,8 @@ VTKWriter::writeMesh(const std::shared_ptr<const IMesh>& mesh) const } void -VTKWriter::write(const std::vector<std::shared_ptr<const NamedDiscreteFunction>>& named_discrete_function_list, - double time) const +VTKWriter::_writeAtTime(const std::vector<std::shared_ptr<const NamedDiscreteFunction>>& named_discrete_function_list, + double time) const { std::shared_ptr mesh = this->_getMesh(named_discrete_function_list); @@ -660,15 +670,15 @@ VTKWriter::write(const std::vector<std::shared_ptr<const NamedDiscreteFunction>> switch (mesh->dimension()) { case 1: { - this->_write(std::dynamic_pointer_cast<const Mesh<Connectivity<1>>>(mesh), output_named_item_data_set, time); + this->_writeAtTime(std::dynamic_pointer_cast<const Mesh<Connectivity<1>>>(mesh), output_named_item_data_set, time); break; } case 2: { - this->_write(std::dynamic_pointer_cast<const Mesh<Connectivity<2>>>(mesh), output_named_item_data_set, time); + this->_writeAtTime(std::dynamic_pointer_cast<const Mesh<Connectivity<2>>>(mesh), output_named_item_data_set, time); break; } case 3: { - this->_write(std::dynamic_pointer_cast<const Mesh<Connectivity<3>>>(mesh), output_named_item_data_set, time); + this->_writeAtTime(std::dynamic_pointer_cast<const Mesh<Connectivity<3>>>(mesh), output_named_item_data_set, time); break; } default: { diff --git a/src/output/VTKWriter.hpp b/src/output/VTKWriter.hpp index 913a05ef1..eb0f70d92 100644 --- a/src/output/VTKWriter.hpp +++ b/src/output/VTKWriter.hpp @@ -95,15 +95,17 @@ class VTKWriter : public WriterBase SerializedDataList& serialized_data_list) const; template <typename MeshType> - void _write(const std::shared_ptr<const MeshType>& mesh, - const OutputNamedItemDataSet& output_named_item_data_set, - double time) const; + void _writeAtTime(const std::shared_ptr<const MeshType>& mesh, + const OutputNamedItemDataSet& output_named_item_data_set, + double time) const; + + void _writeAtTime(const std::vector<std::shared_ptr<const NamedDiscreteFunction>>& named_discrete_function_list, + double time) const final; public: void writeMesh(const std::shared_ptr<const IMesh>& mesh) const final; - void write(const std::vector<std::shared_ptr<const NamedDiscreteFunction>>& named_discrete_function_list, - double time) const final; + VTKWriter(const std::string& base_filename) : WriterBase(base_filename) {} VTKWriter(const std::string& base_filename, const double time_period) : WriterBase(base_filename, time_period) {} diff --git a/src/output/WriterBase.cpp b/src/output/WriterBase.cpp index adf3f4a7f..7ae28e9e8 100644 --- a/src/output/WriterBase.cpp +++ b/src/output/WriterBase.cpp @@ -194,32 +194,27 @@ WriterBase::_getOutputNamedItemDataSet( return named_item_data_set; } -double -WriterBase::getLastTime() const -{ - if (m_saved_times.size() > 0) { - return m_saved_times[m_saved_times.size() - 1]; - } else { - return -std::numeric_limits<double>::max(); - } -} - WriterBase::WriterBase(const std::string& base_filename, const double& time_period) - : m_base_filename{base_filename}, m_time_period{time_period}, m_next_time{0} + : m_base_filename{base_filename}, m_period_manager(time_period) {} +WriterBase::WriterBase(const std::string& base_filename) : m_base_filename{base_filename} {} + void WriterBase::writeIfNeeded(const std::vector<std::shared_ptr<const NamedDiscreteFunction>>& named_discrete_function_list, double time) const { - const double last_time = getLastTime(); - if (time == last_time) - return; // output already performed - - if (time >= m_next_time) { - m_next_time += m_time_period; - this->write(named_discrete_function_list, time); - m_saved_times.push_back(time); + if (m_period_manager.has_value()) { + const double last_time = m_period_manager->getLastTime(); + if (time == last_time) + return; // output already performed + + if (time >= m_period_manager->nextTime()) { + this->_writeAtTime(named_discrete_function_list, time); + m_period_manager->setSaveTime(time); + } + } else { + throw NormalError("Writer has no period defined"); } } @@ -227,9 +222,13 @@ void WriterBase::writeForced(const std::vector<std::shared_ptr<const NamedDiscreteFunction>>& named_discrete_function_list, double time) const { - if (time == getLastTime()) - return; // output already performed + if (m_period_manager.has_value()) { + if (time == m_period_manager->getLastTime()) + return; // output already performed - this->write(named_discrete_function_list, time); - m_saved_times.push_back(time); + this->_writeAtTime(named_discrete_function_list, time); + m_period_manager->setSaveTime(time); + } else { + throw NormalError("Writer has no period defined"); + } } diff --git a/src/output/WriterBase.hpp b/src/output/WriterBase.hpp index 3ba91af28..6d96ee410 100644 --- a/src/output/WriterBase.hpp +++ b/src/output/WriterBase.hpp @@ -2,7 +2,10 @@ #define WRITER_BASE_HPP #include <output/IWriter.hpp> +#include <utils/PugsAssert.hpp> +#include <limits> +#include <optional> #include <string> class IMesh; @@ -10,12 +13,76 @@ class OutputNamedItemDataSet; class WriterBase : public IWriter { + public: + class PeriodManager + { + private: + const double m_time_period; + mutable double m_next_time; + + mutable std::vector<double> m_saved_times; + + public: + double + timePeriod() const + { + return m_time_period; + } + + double + nextTime() const + { + return m_next_time; + } + + void + setNextTime(double next_time) + { + m_next_time = next_time; + } + + size_t + nbSavedTimes() const + { + return m_saved_times.size(); + } + + double + savedTime(size_t i) const + { + Assert(i < m_saved_times.size()); + return m_saved_times[i]; + } + + double + getLastTime() const + { + if (m_saved_times.size() > 0) { + return m_saved_times[m_saved_times.size() - 1]; + } else { + return -std::numeric_limits<double>::max(); + } + } + + void + setSaveTime(double time) const + { + if (m_saved_times.size() == 0) { + m_next_time = time; + } + m_next_time += m_time_period; + m_saved_times.push_back(time); + } + + PeriodManager(const PeriodManager&) = default; + PeriodManager(PeriodManager&&) = default; + PeriodManager(double time_period) : m_time_period{time_period}, m_next_time{-std::numeric_limits<double>::max()} {} + }; + protected: const std::string m_base_filename; - const double m_time_period; - mutable double m_next_time; - mutable std::vector<double> m_saved_times; + std::optional<PeriodManager> m_period_manager; private: template <typename DiscreteFunctionType> @@ -34,12 +101,11 @@ class WriterBase : public IWriter OutputNamedItemDataSet _getOutputNamedItemDataSet( const std::vector<std::shared_ptr<const NamedDiscreteFunction>>& named_discrete_function_list) const; - virtual void write(const std::vector<std::shared_ptr<const NamedDiscreteFunction>>& named_discrete_function_list, - double time) const = 0; + virtual void _writeAtTime( + const std::vector<std::shared_ptr<const NamedDiscreteFunction>>& named_discrete_function_list, + double time) const = 0; public: - double getLastTime() const; - void writeIfNeeded(const std::vector<std::shared_ptr<const NamedDiscreteFunction>>& named_discrete_function_list, double time) const final; @@ -50,6 +116,8 @@ class WriterBase : public IWriter WriterBase(const std::string& base_filename, const double& time_period); + WriterBase(const std::string& base_filename); + virtual ~WriterBase() = default; }; -- GitLab