From 24b9b2991600cdd39651bacfc39efc090583c723 Mon Sep 17 00:00:00 2001 From: "Praetorius, Simon" <simon.praetorius@tu-dresden.de> Date: Mon, 30 Sep 2019 10:47:52 +0200 Subject: [PATCH] Filewriter abstraction --- dune.module | 2 +- examples/boundary.cc | 2 +- examples/convection_diffusion.cc | 2 +- examples/ellipt.cc | 9 +- examples/init/boundary.dat.2d | 1 + examples/init/cahn_hilliard.dat.2d | 12 +- examples/init/ellipt.dat.2d | 1 + examples/init/ellipt.dat.3d | 1 + examples/init/heat.dat.2d | 6 +- examples/init/stokes.dat.2d | 8 +- examples/init/surface.dat.2d | 1 + examples/neumann.cc | 2 +- examples/vecellipt.cc | 2 +- src/amdis/AdaptInfo.hpp | 4 +- src/amdis/BoundaryManager.hpp | 5 + src/amdis/CMakeLists.txt | 2 - src/amdis/FileWriter.hpp | 141 ------------------------ src/amdis/FileWriterInterface.hpp | 68 ------------ src/amdis/ProblemStat.hpp | 31 +++--- src/amdis/ProblemStat.inc.hpp | 170 ++++++++++------------------- src/amdis/ProblemStatBase.hpp | 6 - src/amdis/io/BackupWriter.hpp | 78 +++++++++++++ src/amdis/io/CMakeLists.txt | 10 ++ src/amdis/io/DuneVtkWriter.hpp | 89 +++++++++++++++ src/amdis/io/FileWriterBase.cpp | 36 ++++++ src/amdis/io/FileWriterBase.hpp | 84 ++++++++++++++ src/amdis/io/FileWriterCreator.hpp | 114 +++++++++++++++++++ src/amdis/io/GmshWriter.hpp | 72 ++++++++++++ src/amdis/io/VTKSequenceWriter.hpp | 2 + src/amdis/io/VTKWriter.hpp | 117 ++++++++++++++++++++ test/BackupRestoreTest.cpp | 7 +- 31 files changed, 712 insertions(+), 373 deletions(-) delete mode 100644 src/amdis/FileWriter.hpp delete mode 100644 src/amdis/FileWriterInterface.hpp create mode 100644 src/amdis/io/BackupWriter.hpp create mode 100644 src/amdis/io/DuneVtkWriter.hpp create mode 100644 src/amdis/io/FileWriterBase.cpp create mode 100644 src/amdis/io/FileWriterBase.hpp create mode 100644 src/amdis/io/FileWriterCreator.hpp create mode 100644 src/amdis/io/GmshWriter.hpp create mode 100644 src/amdis/io/VTKWriter.hpp diff --git a/dune.module b/dune.module index fecc6271..d1774028 100644 --- a/dune.module +++ b/dune.module @@ -6,4 +6,4 @@ Module: amdis Version: 0.2 Maintainer: simon.praetorius@tu-dresden.de Depends: dune-common (>= 2.6) dune-geometry (>= 2.6) dune-localfunctions (>= 2.6) dune-typetree (>= 2.6) dune-grid (>= 2.6) dune-functions (>= 2.6) -Suggests: dune-uggrid dune-alugrid dune-foamgrid dune-spgrid dune-istl +Suggests: dune-uggrid dune-alugrid dune-foamgrid dune-spgrid dune-istl dune-vtk diff --git a/examples/boundary.cc b/examples/boundary.cc index 91ef916e..d08280c7 100644 --- a/examples/boundary.cc +++ b/examples/boundary.cc @@ -89,7 +89,7 @@ void run_periodic() prob.assemble(adaptInfo); prob.solve(adaptInfo); - prob.writeFiles(adaptInfo, true); + prob.writeFiles(adaptInfo); } diff --git a/examples/convection_diffusion.cc b/examples/convection_diffusion.cc index b0af5d22..0ba82e9a 100644 --- a/examples/convection_diffusion.cc +++ b/examples/convection_diffusion.cc @@ -37,7 +37,7 @@ int main(int argc, char** argv) AdaptInfo adaptInfo("adapt"); prob.assemble(adaptInfo); prob.solve(adaptInfo); - prob.writeFiles(adaptInfo, true); + prob.writeFiles(adaptInfo); return 0; } diff --git a/examples/ellipt.cc b/examples/ellipt.cc index e032165b..147f6d2e 100644 --- a/examples/ellipt.cc +++ b/examples/ellipt.cc @@ -69,14 +69,11 @@ int main(int argc, char** argv) errL2.push_back(std::sqrt(errorL2)); double errorH1 = errorL2 + integrate(unary_dot(grad_g - gradientAtQP(prob.solution(0))), prob.gridView(), 6); errH1.push_back(std::sqrt(errorH1)); - -#if WRITE_FILES - Dune::VTKWriter<typename ElliptProblem::GridView> vtkWriter(gridView); - vtkWriter.addVertexData(prob.solution(0), Dune::VTK::FieldInfo("u", Dune::VTK::FieldInfo::Type::scalar, 1)); - vtkWriter.write("u_" + std::to_string(l)); -#endif } + // write last solution to file + prob.writeFiles(adaptInfo); + msg(""); msg("{:5} | {:12} | {:12} | {:12} | {:12} | {:12}", "level", "h", "|u - u*|_L2","|u - u*|_H1","eoc_L2","eoc_H1"); diff --git a/examples/init/boundary.dat.2d b/examples/init/boundary.dat.2d index 23f56aeb..d4e033a7 100644 --- a/examples/init/boundary.dat.2d +++ b/examples/init/boundary.dat.2d @@ -8,6 +8,7 @@ ellipt->solver->relative tolerance: 1.e-10 ellipt->solver->info: 1 ellipt->solver->precon: ilu +ellipt->output[0]->format: vtk ellipt->output[0]->filename: boundary.2d ellipt->output[0]->name: u ellipt->output[0]->output directory: ./output diff --git a/examples/init/cahn_hilliard.dat.2d b/examples/init/cahn_hilliard.dat.2d index 56ef77a4..7af9db93 100644 --- a/examples/init/cahn_hilliard.dat.2d +++ b/examples/init/cahn_hilliard.dat.2d @@ -18,19 +18,19 @@ ch->solver->relative tolerance: 1e-6 ch->solver->break if tolerance not reached: 1 ch->solver->info: 2 +ch->output[0]->format: vtk ch->output[0]->filename: phi.2d ch->output[0]->output directory: output ch->output[0]->name: phi -ch->output[0]->ParaView format: 1 -ch->output[0]->ParaView mode: 1 -ch->output[0]->ParaView animation: 1 +ch->output[0]->mode: 1 +ch->output[0]->animation: 1 +ch->output[1]->format: vtk ch->output[1]->filename: mu.2d ch->output[1]->output directory: output ch->output[1]->name: mu -ch->output[1]->ParaView format: 1 -ch->output[1]->ParaView mode: 1 -ch->output[1]->ParaView animation: 1 +ch->output[1]->mode: 1 +ch->output[1]->animation: 1 adapt->timestep: 0.001 adapt->start time: 0.0 diff --git a/examples/init/ellipt.dat.2d b/examples/init/ellipt.dat.2d index bc4dcc23..0ef31af1 100644 --- a/examples/init/ellipt.dat.2d +++ b/examples/init/ellipt.dat.2d @@ -13,6 +13,7 @@ ellipt->solver->max iteration: 10000 ellipt->solver->relative tolerance: 1.e-10 ellipt->solver->precon: ilu +ellipt->output[0]->format: vtk backup ellipt->output[0]->filename: ellipt.2d ellipt->output[0]->name: u ellipt->output[0]->output directory: ./output diff --git a/examples/init/ellipt.dat.3d b/examples/init/ellipt.dat.3d index ad5cbc12..baef5567 100644 --- a/examples/init/ellipt.dat.3d +++ b/examples/init/ellipt.dat.3d @@ -13,6 +13,7 @@ ellipt->solver->max iteration: 10000 ellipt->solver->relative tolerance: 1.e-10 ellipt->solver->precon: ilu +ellipt->output[0]->format: vtk ellipt->output[0]->filename: ellipt.3d ellipt->output[0]->name: u ellipt->output[0]->output directory: ./output diff --git a/examples/init/heat.dat.2d b/examples/init/heat.dat.2d index 4db5cd5e..c23a811c 100644 --- a/examples/init/heat.dat.2d +++ b/examples/init/heat.dat.2d @@ -12,10 +12,12 @@ heat->solver->absolute tolerance: 1e-6 heat->solver->info: 1 heat->solver->precon: ilu +heat->output[0]->format: vtk backup +heat->output[0]->name: u heat->output[0]->filename: heat.2d heat->output[0]->output directory: output -heat->output[0]->ParaView mode: 1 -heat->output[0]->ParaView animation: 1 +heat->output[0]->mode: 1 +heat->output[0]->animation: 1 adapt->timestep: 0.1 adapt->start time: 0.0 diff --git a/examples/init/stokes.dat.2d b/examples/init/stokes.dat.2d index c4ac8b2f..2f3b32cb 100644 --- a/examples/init/stokes.dat.2d +++ b/examples/init/stokes.dat.2d @@ -10,18 +10,18 @@ stokes->solver->relative tolerance: 1e-8 stokes->solver->precon: ilu stokes->solver->info: 2 +stokes->output[0]->format: vtk stokes->output[0]->filename: stokes_u.2d stokes->output[0]->name: u stokes->output[0]->subsampling: 2 stokes->output[0]->output directory: ./output -stokes->output[0]->ParaView format: 1 -stokes->output[0]->ParaView mode: 1 +stokes->output[0]->mode: 1 +stokes->output[1]->format: vtk stokes->output[1]->filename: stokes_p.2d stokes->output[1]->name: p stokes->output[1]->output directory: ./output -stokes->output[1]->ParaView format: 1 -stokes->output[1]->ParaView mode: 1 +stokes->output[1]->mode: 1 stokes->viscosity: 1.0 stokes->density: 1.0 diff --git a/examples/init/surface.dat.2d b/examples/init/surface.dat.2d index 7fad6f50..282ea4d0 100644 --- a/examples/init/surface.dat.2d +++ b/examples/init/surface.dat.2d @@ -9,6 +9,7 @@ surface->solver->relative tolerance: 1.e-6 surface->solver->info: 1 surface->solver->precon: ilu +surface->output[0]->format: vtk surface->output[0]->filename: surface.2d surface->output[0]->name: u surface->output[0]->output directory: ./output diff --git a/examples/neumann.cc b/examples/neumann.cc index 20f07106..1037b813 100644 --- a/examples/neumann.cc +++ b/examples/neumann.cc @@ -45,7 +45,7 @@ void run(Grid& grid) prob.assemble(adaptInfo); prob.solve(adaptInfo); - prob.writeFiles(adaptInfo, true); + prob.writeFiles(adaptInfo); } diff --git a/examples/vecellipt.cc b/examples/vecellipt.cc index 2cb3a414..7f183562 100644 --- a/examples/vecellipt.cc +++ b/examples/vecellipt.cc @@ -51,7 +51,7 @@ int main(int argc, char** argv) #endif prob.solve(adaptInfo); - prob.writeFiles(adaptInfo, true); + prob.writeFiles(adaptInfo); return 0; } diff --git a/src/amdis/AdaptInfo.hpp b/src/amdis/AdaptInfo.hpp index d233e0b3..f03a4ecc 100644 --- a/src/amdis/AdaptInfo.hpp +++ b/src/amdis/AdaptInfo.hpp @@ -733,10 +733,10 @@ namespace AMDiS double lastProcessedTimestep_ = 0.0; /// Minimal step size - double minTimestep_ = 0.0; + double minTimestep_ = std::sqrt(std::numeric_limits<double>::epsilon()); /// Maximal step size - double maxTimestep_ = 1.0; + double maxTimestep_ = std::sqrt(std::numeric_limits<double>::max()); /// Number of current time step int timestepNumber_ = 0; diff --git a/src/amdis/BoundaryManager.hpp b/src/amdis/BoundaryManager.hpp index 1b435839..856e92f6 100644 --- a/src/amdis/BoundaryManager.hpp +++ b/src/amdis/BoundaryManager.hpp @@ -25,6 +25,11 @@ namespace AMDiS return boundaryIds_[intersection.boundarySegmentIndex()]; } + std::vector<BoundaryType> const boundaryIds() const + { + return boundaryIds_; + } + protected: std::vector<BoundaryType> boundaryIds_; // maps a boundarySegementIndex to an ID }; diff --git a/src/amdis/CMakeLists.txt b/src/amdis/CMakeLists.txt index 316e348e..25ca9c6c 100644 --- a/src/amdis/CMakeLists.txt +++ b/src/amdis/CMakeLists.txt @@ -39,8 +39,6 @@ install(FILES DOFVector.inc.hpp DOFVectorInterface.hpp Environment.hpp - FileWriter.hpp - FileWriterInterface.hpp Flag.hpp GridFunctionOperator.hpp GridFunctions.hpp diff --git a/src/amdis/FileWriter.hpp b/src/amdis/FileWriter.hpp deleted file mode 100644 index 22ed7404..00000000 --- a/src/amdis/FileWriter.hpp +++ /dev/null @@ -1,141 +0,0 @@ -#pragma once - -#include <string> -#include <memory> - -#include <dune/functions/functionspacebases/lagrangebasis.hh> -#include <dune/grid/io/file/vtk/vtkwriter.hh> -#include <dune/grid/io/file/vtk/subsamplingvtkwriter.hh> -#include <dune/typetree/childextraction.hh> - -#include <amdis/FileWriterInterface.hpp> -#include <amdis/Initfile.hpp> -#include <amdis/common/Filesystem.hpp> -#include <amdis/common/StaticSize.hpp> -#include <amdis/common/ValueCategory.hpp> -#include <amdis/gridfunctions/DiscreteFunction.hpp> -#include <amdis/io/VTKSequenceWriter.hpp> - -namespace AMDiS -{ - namespace Impl - { - template <class Tag> struct VTKFieldTypeImpl; - template <> - struct VTKFieldTypeImpl<tag::scalar> { - static const Dune::VTK::FieldInfo::Type value = Dune::VTK::FieldInfo::Type::scalar; - }; - template <> - struct VTKFieldTypeImpl<tag::vector> { - static const Dune::VTK::FieldInfo::Type value = Dune::VTK::FieldInfo::Type::vector; - }; - template <> - struct VTKFieldTypeImpl<tag::matrix> { - static const Dune::VTK::FieldInfo::Type value = Dune::VTK::FieldInfo::Type::tensor; - }; - - } // end namespace Impl - - template <class Range> - constexpr Dune::VTK::FieldInfo::Type VTKFieldType = Impl::VTKFieldTypeImpl<ValueCategory_t<Range>>::value; - - template <class Range> - constexpr std::size_t VTKFieldSize = Size_v<Range>; - - - template <class GB, class VT, class TP> - class FileWriter - : public FileWriterInterface - { - using GlobalBasis = GB; - using ValueType = VT; - using TreePath = TP; - - private: - using GridView = typename GlobalBasis::GridView; - using Range = typename DiscreteFunction<GB,VT,TP>::Range; - - /// Dimension of the mesh - static constexpr int dim = GridView::dimension; - - /// Dimension of the world - static constexpr int dow = GridView::dimensionworld; - - public: - /// Constructor. - FileWriter(std::string const& name, DiscreteFunction<GB,VT,TP> const& discreteFct) - : FileWriterInterface(name) - , discreteFct_(discreteFct) - , animation_(false) - { - Parameters::get(name + "->ParaView animation", animation_); - - int m = Parameters::get<int>(name + "->ParaView mode").value_or(0); - mode_ = (m == 0 ? Dune::VTK::ascii : Dune::VTK::appendedraw); - - init(name, ValueCategory_t<Range>{}); - } - - template <class ValueCat> - void init(std::string const& baseName, ValueCat) - { - auto subSampling = Parameters::get<int>(baseName + "->subsampling"); - if (subSampling) - vtkWriter_ = std::make_shared<Dune::SubsamplingVTKWriter<GridView>>(gridView(), subSampling.value()); - else - vtkWriter_ = std::make_shared<Dune::VTKWriter<GridView>>(gridView()); - - if (animation_) - vtkSeqWriter_ = std::make_shared<VTKSequenceWriter<GridView>>(vtkWriter_); - - vtkWriter_->addVertexData(discreteFct_, Dune::VTK::FieldInfo(name_, VTKFieldType<Range>, VTKFieldSize<Range>)); - - test_exit(dir_ == "." || filesystem::exists(dir_), "Output directory '{}' does not exist!",dir_); - } - - void init(std::string const&, tag::unknown) {} - - /// Implements \ref FileWriterInterface::writeFiles - void writeFiles(AdaptInfo& adaptInfo, bool force) override - { - filesystem::create_directories(dir_ + "/_piecefiles"); - if (vtkSeqWriter_) - vtkSeqWriter_->pwrite(adaptInfo.time(), filename_, dir_, "_piecefiles", mode_); - else if (vtkWriter_) - vtkWriter_->pwrite(filename_, dir_, "_piecefiles", mode_); - } - - protected: - GridView const& gridView() const - { - return discreteFct_.basis()->gridView(); - } - - private: - DiscreteFunction<GB,VT,TP> discreteFct_; - - std::shared_ptr<Dune::VTKWriter<GridView>> vtkWriter_; - std::shared_ptr<VTKSequenceWriter<GridView>> vtkSeqWriter_; - - // write .pvd if animation=true, otherwise write only .vtu - bool animation_; - - // represents VTK::OutputType: ascii, appendedraw - Dune::VTK::OutputType mode_; - }; - - template <class GlobalBasis, class ValueType, class TreePath> - auto makeFileWriter(std::string const& name, - DiscreteFunction<GlobalBasis,ValueType,TreePath> const& discreteFct) - { - return FileWriter<GlobalBasis,ValueType,TreePath>{name, discreteFct}; - } - - template <class GlobalBasis, class ValueType, class TreePath> - auto makeFileWriterPtr(std::string const& name, - DiscreteFunction<GlobalBasis,ValueType,TreePath> const& discreteFct) - { - return std::make_unique<FileWriter<GlobalBasis,ValueType,TreePath>>(name, discreteFct); - } - -} // end namespace AMDiS diff --git a/src/amdis/FileWriterInterface.hpp b/src/amdis/FileWriterInterface.hpp deleted file mode 100644 index f8f656de..00000000 --- a/src/amdis/FileWriterInterface.hpp +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once - -#include <string> - -#include <amdis/Initfile.hpp> -#include <amdis/Output.hpp> -#include <amdis/common/Filesystem.hpp> - -namespace AMDiS -{ - // forward declaration - class AdaptInfo; - - class FileWriterInterface - { - public: - explicit FileWriterInterface(std::string const& base) - { - Parameters::get(base + "->filename", filename_); - Parameters::get(base + "->output directory", dir_); - Parameters::get(base + "->name", name_); - } - - virtual ~FileWriterInterface() = default; - - - // pure virtual method to be implemented by derived classes - virtual void writeFiles(AdaptInfo& adaptInfo, bool force) = 0; - - public: // getter and setter - - std::string const& filename() const - { - return filename_; - } - - std::string const& dir() const - { - return dir_; - } - - std::string const& name() const - { - return name_; - } - - void setFilename(std::string const& filename) - { - filename_ = filename; - } - - void setDir(std::string const& dir) - { - dir_ = dir; - } - - void setName(std::string const& name) - { - name_ = name; - } - - protected: - std::string filename_ = "solution"; - std::string dir_ = "."; - std::string name_ = "solution"; - }; - -} // end namespace AMDiS diff --git a/src/amdis/ProblemStat.hpp b/src/amdis/ProblemStat.hpp index 710f33af..02796a2d 100644 --- a/src/amdis/ProblemStat.hpp +++ b/src/amdis/ProblemStat.hpp @@ -37,7 +37,7 @@ #include <amdis/gridfunctions/DiscreteFunction.hpp> #include <amdis/gridfunctions/DOFVectorView.hpp> -#include <amdis/FileWriterInterface.hpp> +#include <amdis/io/FileWriterBase.hpp> #include <amdis/typetree/TreeData.hpp> #include <amdis/typetree/TreePath.hpp> @@ -106,14 +106,21 @@ namespace AMDiS } + /// \brief Initialisation of the problem. /** - * \brief Initialisation of the problem. - * - * Parameters read in initialize() for problem with name 'PROB' - * MESH[0]->global refinements: nr of initial global refinements + * Parameters read in initialize() + * - `[GRID_NAME]->global refinements`: nr of initial global refinements **/ void initialize(Flag initFlag, Self* adoptProblem = nullptr, Flag adoptFlag = INIT_NOTHING); + /// \brief Read the grid and solution from backup files and initialize the problem + /** + * Parameters read in restore() for problem with name 'PROB' + * - `[PROB]->restore->grid`: name of the grid backup file + * - `[PROB]->restore->solution`: name of the solution backup file + **/ + void restore(Flag initFlag); + /// Add an operator to \ref A. /** @{ */ @@ -296,21 +303,9 @@ namespace AMDiS /// Uniform global refinement by n level Flag globalRefine(int n) override; - /// Writes output files. + /// Writes output files. If force=true write even if timestep out of write rhythm. void writeFiles(AdaptInfo& adaptInfo, bool force = false); - /// Backup the grid - void backup(std::string const& filename) const; - - /// Implements \ref ProblemStatBase::backup - void backup(AdaptInfo& adaptInfo) override; - - /// Retore the grid - auto restore(std::string const& filename); - - /// Implements \ref ProblemStatBase::restore - void restore(Flag initFlag) override; - public: // get-methods diff --git a/src/amdis/ProblemStat.inc.hpp b/src/amdis/ProblemStat.inc.hpp index 71775277..c6e7fe9f 100644 --- a/src/amdis/ProblemStat.inc.hpp +++ b/src/amdis/ProblemStat.inc.hpp @@ -12,10 +12,10 @@ #include <amdis/AdaptInfo.hpp> #include <amdis/BackupRestore.hpp> -#include <amdis/FileWriter.hpp> #include <amdis/Assembler.hpp> #include <amdis/GridFunctionOperator.hpp> #include <amdis/GridTransferManager.hpp> +#include <amdis/io/FileWriterCreator.hpp> #include <amdis/linearalgebra/SymmetryStructure.hpp> namespace AMDiS { @@ -131,6 +131,48 @@ void ProblemStat<Traits>::initialize( } +template <class Traits> +void ProblemStat<Traits>:: +restore(Flag initFlag) +{ + std::string grid_filename = Parameters::get<std::string>(name_ + "->restore->grid").value(); + std::string solution_filename = Parameters::get<std::string>(name_ + "->restore->solution").value(); + test_exit(filesystem::exists(grid_filename), "Restore file '{}' not found.", grid_filename); + test_exit(filesystem::exists(solution_filename), "Restore file '{}' not found.", solution_filename); + + // restore grid from file + if (Dune::Capabilities::hasBackupRestoreFacilities<Grid>::v) + adoptGrid(std::unique_ptr<Grid>(Dune::BackupRestoreFacility<Grid>::restore(grid_filename))); + else + adoptGrid(std::unique_ptr<Grid>(BackupRestoreByGridFactory<Grid>::restore(grid_filename))); + + // create fespace + if (initFlag.isSet(INIT_FE_SPACE) || initFlag.isSet(INIT_SYSTEM)) + createGlobalBasis(); + + // create system + if (initFlag.isSet(INIT_SYSTEM)) + createMatricesAndVectors(); + + // create solver + if (linearSolver_) + warning("solver already created\n"); + else if (initFlag.isSet(INIT_SOLVER)) + createSolver(); + + // create marker + if (initFlag.isSet(INIT_MARKER)) + createMarker(); + + // create file writer + if (initFlag.isSet(INIT_FILEWRITER)) + createFileWriter(); + + solution_->resize(); + solution_->restore(solution_filename); +} + + template <class Traits> void ProblemStat<Traits>::createGrid() { @@ -256,17 +298,29 @@ void ProblemStat<Traits>::createMarker() template <class Traits> void ProblemStat<Traits>::createFileWriter() { + FileWriterCreator<CoefficientVector> creator(solution_, boundaryManager_); + filewriter_.clear(); auto localView = globalBasis_->localView(); - for_each_node(localView.tree(), [&,this](auto const& node, auto treePath) -> void + for_each_node(localView.tree(), [&](auto const& /*node*/, auto treePath) -> void { std::string componentName = name_ + "->output[" + to_string(treePath) + "]"; + auto format = Parameters::get<std::vector<std::string>>(componentName + "->format"); + + if (!format && to_string(treePath).empty()) { + // alternative for root treepath + componentName = name_ + "->output"; + format = Parameters::get<std::vector<std::string>>(componentName + "->format"); + } - if (!Parameters::get<std::string>(componentName + "->filename")) + if (!format) return; - auto writer = makeFileWriterPtr(componentName, this->solution(treePath)); - filewriter_.push_back(std::move(writer)); + for (std::string const& type : format.value()) { + auto writer = creator.create(type, componentName, treePath); + if (writer) + filewriter_.push_back(std::move(writer)); + } }); } @@ -518,112 +572,8 @@ writeFiles(AdaptInfo& adaptInfo, bool force) { Dune::Timer t; for (auto writer : filewriter_) - writer->writeFiles(adaptInfo, force); + writer->write(adaptInfo, force); msg("writeFiles needed {} seconds", t.elapsed()); } - -template <class Grid, class GridView, - class = decltype(Dune::BackupRestoreFacility<Grid>::backup(std::declval<Grid>(), std::string("")))> -void backup_impl(Grid const& grid, GridView const& gv, std::string filename, std::true_type) -{ - Dune::BackupRestoreFacility<Grid>::backup(grid, filename); -} - -template <class Grid, class GridView, bool B, - class = decltype(BackupRestoreByGridFactory<Grid>::backup(std::declval<GridView>(), std::string("")))> -void backup_impl(Grid const& grid, GridView const& gv, std::string filename, bool_t<B>) -{ - warning("Falling back to backup of gridview."); - BackupRestoreByGridFactory<Grid>::backup(gv, filename); -} - -template <class Traits> -void ProblemStat<Traits>:: -backup(std::string const& filename) const -{ - backup_impl(*grid_, gridView(), filename, bool_t<Dune::Capabilities::hasBackupRestoreFacilities<Grid>::v>{}); -} - - -template <class Traits> -void ProblemStat<Traits>:: -backup(AdaptInfo& adaptInfo) -{ - auto param = Parameters::get<std::string>(name_ + "->backup->grid"); - std::string grid_filename = param ? *param : - name_ + "_" + std::to_string(adaptInfo.timestepNumber()) + ".grid"; - - auto param2 = Parameters::get<std::string>(name_ + "->backup->solution"); - std::string solution_filename = param2 ? *param2 : - name_ + "_" + std::to_string(adaptInfo.timestepNumber()) + ".solution"; - - backup(grid_filename); - solution_->backup(solution_filename); - msg("Problem backuped to files '{}' and '{}'.", grid_filename, solution_filename); -} - - -template <class Grid, - class = decltype(Dune::BackupRestoreFacility<Grid>::restore(std::string("")))> -auto restore_impl(std::string filename, std::true_type) -{ - return Dune::BackupRestoreFacility<Grid>::restore(filename); -} - -template <class Grid, bool B, - class = decltype(BackupRestoreByGridFactory<Grid>::restore(std::string("")))> -auto restore_impl(std::string filename, bool_t<B>) -{ - return BackupRestoreByGridFactory<Grid>::restore(filename); -} - -template <class Traits> -auto ProblemStat<Traits>:: -restore(std::string const& filename) -{ - // restore grid from file - std::unique_ptr<Grid> grid(restore_impl<Grid>(filename, bool_t<Dune::Capabilities::hasBackupRestoreFacilities<Grid>::v>{})); - return std::move(grid); -} - - -template <class Traits> -void ProblemStat<Traits>:: -restore(Flag initFlag) -{ - std::string grid_filename = Parameters::get<std::string>(name_ + "->restore->grid").value(); - std::string solution_filename = Parameters::get<std::string>(name_ + "->restore->solution").value(); - test_exit(filesystem::exists(grid_filename), "Restore file '{}' not found.", grid_filename); - test_exit(filesystem::exists(solution_filename), "Restore file '{}' not found.", solution_filename); - - // restore grid from file - adoptGrid(restore(grid_filename)); - - // create fespace - if (initFlag.isSet(INIT_FE_SPACE) || initFlag.isSet(INIT_SYSTEM)) - createGlobalBasis(); - - // create system - if (initFlag.isSet(INIT_SYSTEM)) - createMatricesAndVectors(); - - // create solver - if (linearSolver_) - warning("solver already created\n"); - else if (initFlag.isSet(INIT_SOLVER)) - createSolver(); - - // create marker - if (initFlag.isSet(INIT_MARKER)) - createMarker(); - - // create file writer - if (initFlag.isSet(INIT_FILEWRITER)) - createFileWriter(); - - solution_->resizeZero(); - solution_->restore(solution_filename); -} - } // end namespace AMDiS diff --git a/src/amdis/ProblemStatBase.hpp b/src/amdis/ProblemStatBase.hpp index df333cff..81f4a7cf 100644 --- a/src/amdis/ProblemStatBase.hpp +++ b/src/amdis/ProblemStatBase.hpp @@ -111,12 +111,6 @@ namespace AMDiS */ virtual void estimate(AdaptInfo& adaptInfo) = 0; - /// \brief backup the grid and the solution to a file - virtual void backup(AdaptInfo& adaptInfo) = 0; - - /// \brief restore the grid and the solution from a file - virtual void restore(Flag initFlag) = 0; - /// Returns the name of the problem. virtual std::string const& name() const = 0; }; diff --git a/src/amdis/io/BackupWriter.hpp b/src/amdis/io/BackupWriter.hpp new file mode 100644 index 00000000..45aa4497 --- /dev/null +++ b/src/amdis/io/BackupWriter.hpp @@ -0,0 +1,78 @@ +#pragma once + +#include <string> +#include <memory> +#include <utility> + +#include <dune/grid/common/backuprestore.hh> +#include <dune/grid/common/capabilities.hh> + +#include <amdis/BackupRestore.hpp> +#include <amdis/Initfile.hpp> +#include <amdis/Output.hpp> +#include <amdis/common/Filesystem.hpp> +#include <amdis/io/FileWriterBase.hpp> + +namespace AMDiS +{ + template <class SystemVector> + class BackupWriter + : public FileWriterBase + { + using GlobalBasis = typename SystemVector::GlobalBasis; + using GridView = typename GlobalBasis::GridView; + using Grid = typename GridView::Grid; + + public: + /// Constructor. + BackupWriter(std::string const& name, std::shared_ptr<SystemVector> systemVector) + : FileWriterBase(name) + , systemVector_(std::move(systemVector)) + { + Parameters::get(name + "->animation", animation_); + } + + /// Implements \ref FileWriterBase::write + void write(AdaptInfo& adaptInfo, bool force) override + { + std::string filename = filesystem::path({this->dir(), this->filename()}).string(); + + if (animation_) + filename += "_" + std::to_string(adaptInfo.timestepNumber()); + + if (force || this->doWrite(adaptInfo)) { + GridView const& gridView = systemVector_->basis()->gridView(); + backupGrid(gridView, filename + ".grid", + bool_t<Dune::Capabilities::hasBackupRestoreFacilities<Grid>::v>{}); + systemVector_->backup(filename + ".solution"); + + msg("Backup written to files '{}' and '{}'.", filename + ".grid", filename + ".solution"); + } + } + + + private: + + template <class G = Grid, + class = decltype(Dune::BackupRestoreFacility<G>::backup(std::declval<G>(), std::string("")))> + void backupGrid(GridView const& gv, std::string filename, std::true_type) + { + Dune::BackupRestoreFacility<Grid>::backup(gv.grid(), filename); + } + + template <bool B, class G = Grid, class GV = GridView, + class = decltype(BackupRestoreByGridFactory<G>::backup(std::declval<GV>(), std::string("")))> + void backupGrid(GridView const& gv, std::string filename, bool_t<B>) + { + warning("Falling back to backup of gridview."); + BackupRestoreByGridFactory<Grid>::backup(gv, filename); + } + + private: + std::shared_ptr<SystemVector> systemVector_; + + /// append timestepnumber if animation=true, otherwise always override + bool animation_ = false; + }; + +} // end namespace AMDiS diff --git a/src/amdis/io/CMakeLists.txt b/src/amdis/io/CMakeLists.txt index d367155d..2f1f42aa 100644 --- a/src/amdis/io/CMakeLists.txt +++ b/src/amdis/io/CMakeLists.txt @@ -1,3 +1,13 @@ +dune_library_add_sources(amdis SOURCES + FileWriterBase.cpp +) + install(FILES + BackupWriter.hpp + DuneVtkWriter.hpp + FileWriterBase.hpp + FileWriterCreator.hpp + GmshWriter.hpp VTKSequenceWriter.hpp + VTKWriter.hpp DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/amdis/io) diff --git a/src/amdis/io/DuneVtkWriter.hpp b/src/amdis/io/DuneVtkWriter.hpp new file mode 100644 index 00000000..60b9fd8a --- /dev/null +++ b/src/amdis/io/DuneVtkWriter.hpp @@ -0,0 +1,89 @@ +#pragma once + +#include <string> +#include <memory> + +#if HAVE_DUNE_VTK + +#include <dune/vtk/pvdwriter.hh> +#include <dune/vtk/vtkwriter.hh> + +#include <amdis/Initfile.hpp> +#include <amdis/common/Filesystem.hpp> +#include <amdis/io/FileWriterBase.hpp> + +namespace AMDiS +{ + /// Adapter for the dune-vtk writer + template <class GB, class VT, class TP> + class DuneVtkWriter + : public FileWriterBase + { + using GridView = typename GB::GridView; + using Writer = Dune::VtkWriter<GridView>; + using SeqWriter = Dune::PvdWriter<Writer>; + + public: + /// Constructor. + DuneVtkWriter(std::string const& name, DiscreteFunction<GB,VT,TP> const& discreteFct) + : FileWriterBase(name) + , discreteFct_(discreteFct) + { + int m = 0, p = 0; + Parameters::get(name + "->animation", animation_); + Parameters::get(name + "->mode", m); + Parameters::get(name + "->precision", p); + + Dune::Vtk::FormatTypes mode = + m == 0 ? Dune::Vtk::ASCII : + m == 1 ? Dune::Vtk::BINARY : + Dune::Vtk::COMPRESSED; + + Dune::Vtk::DataTypes precision = + p == 0 ? Dune::Vtk::FLOAT32 : + Dune::Vtk::FLOAT64; + + if (animation_) { + vtkSeqWriter_ = std::make_shared<SeqWriter>(gridView(), mode, precision); + vtkSeqWriter_->addPointData(discreteFct_, this->name()); + } else { + vtkWriter_ = std::make_shared<Writer>(gridView(), mode, precision); + vtkWriter_->addPointData(discreteFct_, this->name()); + } + } + + /// Implements \ref FileWriterBase::write + void write(AdaptInfo& adaptInfo, bool force) override + { + std::string data_dir = this->dir() + "/_piecefiles"; + filesystem::create_directories(data_dir); + + std::string filename = filesystem::path({this->dir(), this->filename() + ".vtk"}).string(); + if (force || this->doWrite(adaptInfo)) { + if (animation_) + vtkSeqWriter_->writeTimestep(adaptInfo.time(), filename, data_dir, true); + else + vtkWriter_->write(filename, data_dir); + } + } + + private: + /// The Gridview this writer lives on. Given by the discrete function. + GridView const& gridView() const + { + return discreteFct_.basis()->gridView(); + } + + private: + DiscreteFunction<GB,VT,TP> discreteFct_; + + std::shared_ptr<Writer> vtkWriter_; + std::shared_ptr<SeqWriter> vtkSeqWriter_; + + /// write .pvd if animation=true, otherwise write only .vtu + bool animation_ = false; + }; + +} // end namespace AMDiS + +#endif // HAVE_DUNE_VTK diff --git a/src/amdis/io/FileWriterBase.cpp b/src/amdis/io/FileWriterBase.cpp new file mode 100644 index 00000000..009bf000 --- /dev/null +++ b/src/amdis/io/FileWriterBase.cpp @@ -0,0 +1,36 @@ +#include "FileWriterBase.hpp" + +#include <amdis/AdaptInfo.hpp> +#include <amdis/Initfile.hpp> +#include <amdis/common/Filesystem.hpp> + +namespace AMDiS +{ + +FileWriterBase::FileWriterBase(std::string const& base) +{ + Parameters::get(base + "->filename", filename_); + Parameters::get(base + "->output directory", dir_); + Parameters::get(base + "->name", name_); + Parameters::get(base + "->write every i-th timestep", tsModulo_); + Parameters::get(base + "->write after timestep", timeModulo_); + + test_exit(dir_ == "." || filesystem::exists(dir_), "Output directory '{}' does not exist!", dir_); +} + + +bool FileWriterBase::doWrite(AdaptInfo& adaptInfo) const +{ + if (timeModulo_ > 0.0 && + lastWriteTime_ > adaptInfo.startTime() && + lastWriteTime_ + timeModulo_ > adaptInfo.time() + 0.5*adaptInfo.minTimestep()) + return false; + + else if (tsModulo_ > 0 && adaptInfo.timestepNumber() % tsModulo_ != 0) + return false; + + lastWriteTime_ = adaptInfo.time(); + return true; +} + +} // end namespace AMDiS diff --git a/src/amdis/io/FileWriterBase.hpp b/src/amdis/io/FileWriterBase.hpp new file mode 100644 index 00000000..81065825 --- /dev/null +++ b/src/amdis/io/FileWriterBase.hpp @@ -0,0 +1,84 @@ +#pragma once + +#include <limits> +#include <string> + +namespace AMDiS +{ + // forward declaration + class AdaptInfo; + + /// Interface class for filewriters + class FileWriterInterface + { + public: + /// Virtual destructor + virtual ~FileWriterInterface() = default; + + /// Pure virtual method to be implemented by derived classes + virtual void write(AdaptInfo& adaptInfo, bool force) = 0; + }; + + /// \brief Base class for filewriters + /** + * Read parameters common for all filewriters, where `BASE` is given by the + * constructor parameter `base`: + * - `[BASE]->filename`: Base name of the filename, not including the file extension + * - `[BASE]->output directory`: Directory where to put the files + * - `[BASE]->name`: Name of the data vector in the output file + * - `[BASE]->write every i-th timestep`: Timestep number interval. + * - `[BASE]->write after timestep`: Time interval. + * + * Some other parameters found in some filewriter implementations: + * - `[BASE]->mode`: File mode, either ASCII=0, BINARY=1, or COMPRESSED=2 + * - `[BASE]->precision`: Output precision, either FLOAT=0, DOUBLE=1 + * - `[BASE]->animation`: Write animation files, or append the timestep to the filename. + **/ + class FileWriterBase + : public FileWriterInterface + { + public: + /// Constructor. Reads common parameters. + FileWriterBase(std::string const& base); + + /// Return whether to write the current timestep or not + bool doWrite(AdaptInfo& adaptInfo) const; + + public: + std::string const& filename() const + { + return filename_; + } + + std::string const& dir() const + { + return dir_; + } + + std::string const& name() const + { + return name_; + } + + protected: + /// Base part of output filename + std::string filename_ = "solution"; + + /// Output directory + std::string dir_ = "."; + + /// Name of the data + std::string name_ = "solution"; + + /// Write every i'th timestep + int tsModulo_ = 0; + + /// Write after every time interval + double timeModulo_ = 0.0; + + private: + // time counter for the interval output + mutable double lastWriteTime_ = std::numeric_limits<double>::lowest(); + }; + +} // end namespace AMDiS diff --git a/src/amdis/io/FileWriterCreator.hpp b/src/amdis/io/FileWriterCreator.hpp new file mode 100644 index 00000000..1193f19b --- /dev/null +++ b/src/amdis/io/FileWriterCreator.hpp @@ -0,0 +1,114 @@ +#pragma once + +#include <memory> +#include <string> + +#include <amdis/BoundaryManager.hpp> +#include <amdis/LinearAlgebra.hpp> +#include <amdis/Output.hpp> +#include <amdis/gridfunctions/DiscreteFunction.hpp> +#include <amdis/io/BackupWriter.hpp> +#include <amdis/io/DuneVtkWriter.hpp> +#include <amdis/io/FileWriterBase.hpp> +#include <amdis/io/GmshWriter.hpp> +#include <amdis/io/VTKWriter.hpp> + +namespace AMDiS +{ + /// \brief Creator class for filewriters depending on a given type name + /** + * \tparam SystemVector Type of the DOFVector to write with the filewriter + **/ + template <class SystemVector> + class FileWriterCreator + { + using GlobalBasis = typename SystemVector::GlobalBasis; + using GridView = typename GlobalBasis::GridView; + using Grid = typename GridView::Grid; + + public: + /// Constructor. Stores the pointer to the systemVector and to the (optional) boundaryManager. + FileWriterCreator(std::shared_ptr<SystemVector> systemVector, + std::shared_ptr<BoundaryManager<Grid>> boundaryManager = nullptr) + : systemVector_(std::move(systemVector)) + , boundaryManager_(std::move(boundaryManager)) + {} + + /// Create a new FileWriter of type `type` + /** + * \param type String representing the type of the writer. One of {vtk, dune-vtk, gmsh, backup} + * \param prefix The initfile prefix tp configure the filewriter + * \param treePath Treepath to the component of the systemVector to be handled by the fileWriter. + **/ + template <class TreePath = RootTreePath> + std::unique_ptr<FileWriterInterface> + create(std::string type, std::string prefix, TreePath treePath = {}) const + { + auto data = makeDiscreteFunction(*systemVector_, treePath); + using Range = typename TYPEOF(data)::Range; + + return create_impl(std::move(type), std::move(prefix), data, ValueCategory_t<Range>{}); + } + + private: + template <class GB, class VT, class TP, class ValCat> + std::unique_ptr<FileWriterInterface> + create_impl(std::string type, std::string prefix, DiscreteFunction<GB,VT,TP> const& data, ValCat) const + { + // ParaView VTK format, writer from dune-grid + if (type == "vtk") + { + return std::make_unique<VTKWriter<GB,VT,TP>>(prefix, data); + } +#if HAVE_DUNE_VTK + // ParaView VTK format, writer from dune-vtk + else if (type == "dune-vtk") + { + return std::make_unique<DuneVtkWriter<GB,VT,TP>>(prefix, data); + } +#endif + // GMsh file format, writing just the grid and optionally boundary ids + else if (type == "gmsh") + { + GridView const& gridView = systemVector_->basis()->gridView(); + if (!!boundaryManager_) + return std::make_unique<GmshWriter<typename GB::GridView>>(prefix, gridView, + std::vector<int>{}, boundaryManager_->boundaryIds()); + else + return std::make_unique<GmshWriter<typename GB::GridView>>(prefix, gridView); + } + // Backup writer, writing the grid and the solution vector + else if (type == "backup") + { + return std::make_unique<BackupWriter<SystemVector>>(prefix, systemVector_); + } + + error_exit("Unknown filewriter type '{}' given for '{}'. Use one of " + "(vtk, gmsh, backup, [dune-vtk]), where the last one is only available " + "if the dune module dune-vtk is found.", type, prefix); + return {}; + } + + // The value-category is unknown, like a composite/hierarchic vector or any unknown type. + template <class GB, class VT, class TP> + std::unique_ptr<FileWriterInterface> + create_impl(std::string type, std::string prefix, DiscreteFunction<GB,VT,TP> const& /*data*/, tag::unknown) const + { + // Backup writer, writing the grid and the solution vector + if (type == "backup") + { + return std::make_unique<BackupWriter<SystemVector>>(prefix, systemVector_); + } + + error_exit("Filewriter '{}' cannot be applied to this component in the tree. " + "Either use the writer 'backup' to write the whole tree, or add a treepath " + "to the output prefix '{}'.", type, prefix); + return {}; + } + + private: + std::shared_ptr<SystemVector> systemVector_; + std::shared_ptr<BoundaryManager<Grid>> boundaryManager_ = nullptr; + }; + +} // end namespace AMDiS diff --git a/src/amdis/io/GmshWriter.hpp b/src/amdis/io/GmshWriter.hpp new file mode 100644 index 00000000..0082680c --- /dev/null +++ b/src/amdis/io/GmshWriter.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include <string> +#include <limits> +#include <memory> +#include <utility> + +#include <dune/grid/io/file/gmshwriter.hh> + +#include <amdis/Initfile.hpp> +#include <amdis/Output.hpp> +#include <amdis/common/Filesystem.hpp> +#include <amdis/io/FileWriterBase.hpp> + +namespace AMDiS +{ + /// The GmshWriter just writes the grid of a given gridView to a gmsh compatible .msh file + template <class GV> + class GmshWriter + : public FileWriterBase + { + using GridView = GV; + using Writer = Dune::GmshWriter<GridView>; + + public: + /// Constructor. + GmshWriter(std::string const& name, GridView const& gridView, + std::vector<int> const& physicalEntities = std::vector<int>(), + std::vector<int> const& physicalBoundaries = std::vector<int>()) + : FileWriterBase(name) + , gridView_(gridView) + , physicalEntities_(physicalEntities) + , physicalBoundaries_(physicalBoundaries) + { + int p = 0; + Parameters::get(name + "->animation", animation_); + Parameters::get(name + "->precision", p); + + int precision = (p == 0) + ? std::numeric_limits<float>::max_digits10 + : std::numeric_limits<double>::max_digits10; + + writer_ = std::make_shared<Writer>(gridView_, precision); + } + + /// Implements \ref FileWriterBase::write + void write(AdaptInfo& adaptInfo, bool force) override + { + std::string filename = this->filename(); + if (animation_) + filename += "_" + std::to_string(adaptInfo.time()); + + if (force || this->doWrite(adaptInfo)) { + writer_->write(filesystem::path({this->dir(), filename + ".msh"}).string(), + physicalEntities_, physicalBoundaries_); + + msg("Grid written to file '{}'.", filesystem::path({this->dir(), filename + ".msh"}).string()); + } + } + + private: + GridView gridView_; + std::vector<int> const& physicalEntities_; + std::vector<int> const& physicalBoundaries_; + + std::shared_ptr<Writer> writer_; + + /// write .pvd if animation=true, otherwise write only .vtu + bool animation_ = false; + }; + +} // end namespace AMDiS diff --git a/src/amdis/io/VTKSequenceWriter.hpp b/src/amdis/io/VTKSequenceWriter.hpp index 3311ecda..bbb17a49 100644 --- a/src/amdis/io/VTKSequenceWriter.hpp +++ b/src/amdis/io/VTKSequenceWriter.hpp @@ -12,6 +12,8 @@ #include <dune/grid/io/file/vtk/vtkwriter.hh> +#include <amdis/Environment.hpp> + namespace AMDiS { /// \brief class to write pvd-files which contains a list of all collected vtk-files diff --git a/src/amdis/io/VTKWriter.hpp b/src/amdis/io/VTKWriter.hpp new file mode 100644 index 00000000..d487ed56 --- /dev/null +++ b/src/amdis/io/VTKWriter.hpp @@ -0,0 +1,117 @@ +#pragma once + +#include <string> +#include <memory> + +#include <dune/grid/io/file/vtk/subsamplingvtkwriter.hh> +#include <dune/grid/io/file/vtk/vtkwriter.hh> + +#include <amdis/Initfile.hpp> +#include <amdis/common/Filesystem.hpp> +#include <amdis/common/StaticSize.hpp> +#include <amdis/common/ValueCategory.hpp> +#include <amdis/io/FileWriterBase.hpp> +#include <amdis/io/VTKSequenceWriter.hpp> + +namespace AMDiS +{ + namespace Impl + { + template <class Tag> struct VTKFieldTypeImpl; + template <> + struct VTKFieldTypeImpl<tag::scalar> { + static const Dune::VTK::FieldInfo::Type value = Dune::VTK::FieldInfo::Type::scalar; + }; + template <> + struct VTKFieldTypeImpl<tag::vector> { + static const Dune::VTK::FieldInfo::Type value = Dune::VTK::FieldInfo::Type::vector; + }; + template <> + struct VTKFieldTypeImpl<tag::matrix> { + static const Dune::VTK::FieldInfo::Type value = Dune::VTK::FieldInfo::Type::tensor; + }; + + } // end namespace Impl + + + /// Adapter for the dune-grid VTKWriter + template <class GB, class VT, class TP> + class VTKWriter + : public FileWriterBase + { + using GridView = typename GB::GridView; + using Writer = Dune::VTKWriter<GridView>; + using SeqWriter = VTKSequenceWriter<GridView>; + using Range = typename DiscreteFunction<GB,VT,TP>::Range; + + template <class R> + static constexpr Dune::VTK::FieldInfo::Type VTKFieldType() { + return Impl::VTKFieldTypeImpl<ValueCategory_t<R>>::value; + } + + template <class R> + static constexpr std::size_t VTKFieldSize() { + return Size_v<R>; + } + + public: + /// Constructor. + VTKWriter(std::string const& name, DiscreteFunction<GB,VT,TP> const& discreteFct) + : FileWriterBase(name) + , discreteFct_(discreteFct) + { + int m = 0; + Parameters::get(name + "->animation", animation_); + Parameters::get(name + "->mode", m); + + mode_ = (m == 0) + ? Dune::VTK::ascii + : Dune::VTK::appendedraw; + + auto subSampling = Parameters::get<int>(name + "->subsampling"); + if (subSampling) { + using SubsamplingWriter = Dune::SubsamplingVTKWriter<GridView>; + vtkWriter_ = std::make_shared<SubsamplingWriter>(gridView(), subSampling.value()); + } else { + vtkWriter_ = std::make_shared<Writer>(gridView()); + } + + if (animation_) + vtkSeqWriter_ = std::make_shared<SeqWriter>(vtkWriter_); + + vtkWriter_->addVertexData(discreteFct_, + Dune::VTK::FieldInfo(name_, VTKFieldType<Range>(), VTKFieldSize<Range>())); + } + + /// Implements \ref FileWriterInterface::write + void write(AdaptInfo& adaptInfo, bool force) override + { + filesystem::create_directories(this->dir() + "/_piecefiles"); + if (force || this->doWrite(adaptInfo)) { + if (animation_) + vtkSeqWriter_->pwrite(adaptInfo.time(), this->filename(), this->dir(), "_piecefiles", mode_); + else + vtkWriter_->pwrite(this->filename(), this->dir(), "_piecefiles", mode_); + } + } + + private: + /// The Gridview this writer lives on. Given by the discrete function. + GridView const& gridView() const + { + return discreteFct_.basis()->gridView(); + } + + private: + DiscreteFunction<GB,VT,TP> discreteFct_; + std::shared_ptr<Writer> vtkWriter_; + std::shared_ptr<SeqWriter> vtkSeqWriter_; + + // write .pvd if animation=true, otherwise write only .vtu + bool animation_ = false; + + // represents VTK::OutputType: ascii, appendedraw + Dune::VTK::OutputType mode_ = Dune::VTK::ascii; + }; + +} // end namespace AMDiS diff --git a/test/BackupRestoreTest.cpp b/test/BackupRestoreTest.cpp index f00d1c15..4f6cc20f 100644 --- a/test/BackupRestoreTest.cpp +++ b/test/BackupRestoreTest.cpp @@ -47,7 +47,7 @@ void test(Factory factory) num_vertices = prob.grid()->size(Grid::dimension); AdaptInfo adaptInfo("adapt"); - prob.backup(adaptInfo); + prob.writeFiles(adaptInfo, true); } // restore @@ -97,11 +97,12 @@ int main(int argc, char** argv) Environment env(argc, argv); std::string filename = "test"; - Parameters::set("test->backup->grid", filename + "_" + std::to_string(GRID_ID) + ".grid"); Parameters::set("test->restore->grid", filename + "_" + std::to_string(GRID_ID) + ".grid"); - Parameters::set("test->backup->solution", filename + "_" + std::to_string(GRID_ID) + ".solution"); Parameters::set("test->restore->solution", filename + "_" + std::to_string(GRID_ID) + ".solution"); + Parameters::set("test->output->format", "backup"); + Parameters::set("test->output->filename", filename + "_" + std::to_string(GRID_ID)); + #if GRID_ID == 0 test_cube<Dune::YaspGrid<2>>(); test_cube<Dune::YaspGrid<3>>(); -- GitLab