Commit df5edefd authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

added optional directory argument to file writer

parent ba7a8410
#pragma once
#include <string>
#include <dune/common/std/optional.hh>
namespace Dune
{
......@@ -10,8 +11,8 @@ namespace Dune
/// Virtual destructor
virtual ~FileWriter () = default;
/// Write to file given by `filename`
virtual void write (std::string const& filename) const = 0;
/// Write to file given by `filename` and (optionally) store additional data in `dataDir`
virtual void write (std::string const& filename, Std::optional<std::string> dataDir = {}) const = 0;
};
} // end namespace Dune
......@@ -34,14 +34,23 @@ namespace Dune
* Create timestep files for the data associated to the current timestep `time`.
*
* \param time The time value of the written data
* \param fn Filename of the file to write to. Is stored in \ref timesteps_.
* \param fn Filename of the PVD file to write to. The base part is used to
* create filenames for the timestep files that are stored in \ref timesteps_.
* May contain directory and any filename extension.
* \param dir Specifies where to write the timestep files.
* \param writeCollection Create a collection .pvd file directly
**/
void writeTimestep (double time, std::string const& fn, bool writeCollection = true) const;
void writeTimestep (double time, std::string const& fn, Std::optional<std::string> dir = {},
bool writeCollection = true) const;
/// Writes collection of timesteps to .pvd file.
// NOTE: requires an aforging call to \ref writeTimestep
virtual void write (std::string const& fn) const override;
/**
* \param fn The filename of the PVD file. May contain directory and any filename extension.
* \param dir (Ignored) Timestep files are already written and their filenames are
* stored in \ref timesteps_.
**/
virtual void write (std::string const& fn, Std::optional<std::string> dir = {}) const override;
/// Attach point data to the writer, \see VtkFunction for possible arguments
template <class Function, class... Args>
......
......@@ -9,30 +9,32 @@ namespace Dune {
template <class W>
void PvdWriter<W>
::writeTimestep (double time, std::string const& fn, bool writeCollection) const
::writeTimestep (double time, std::string const& fn, Std::optional<std::string> dir, bool writeCollection) const
{
auto p = filesystem::path(fn);
auto name = p.stem();
p.remove_filename();
p /= name.string();
filesystem::path fn_dir = p;
filesystem::path data_dir = dir ? filesystem::path(*dir) : fn_dir;
filesystem::path rel_dir = filesystem::relative(data_dir, fn_dir);
std::string pvd_fn = fn_dir.string() + '/' + name.string();
std::string seq_fn = data_dir.string() + '/' + name.string() + "_t" + std::to_string(timesteps_.size());
std::string rel_fn = rel_dir.string() + '/' + name.string() + "_t" + std::to_string(timesteps_.size());
std::string ext = "." + vtkWriter_.getFileExtension();
std::string filename = p.string() + "_t" + std::to_string(timesteps_.size());
int rank = 0;
int num_ranks = 1;
#ifdef HAVE_MPI
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &num_ranks);
if (num_ranks > 1)
int rank = vtkWriter_.rank_;
int numRanks = vtkWriter_.numRanks_;
if (numRanks > 1)
ext = ".p" + vtkWriter_.getFileExtension();
#endif
timesteps_.emplace_back(time, filename + ext);
vtkWriter_.write(filename + ext);
timesteps_.emplace_back(time, rel_fn + ext);
vtkWriter_.write(seq_fn + ext);
if (rank == 0 && writeCollection) {
std::ofstream out(p.string() + ".pvd", std::ios_base::ate | std::ios::binary);
std::ofstream out(pvd_fn + ".pvd", std::ios_base::ate | std::ios::binary);
assert(out.is_open());
out.imbue(std::locale::classic());
......@@ -47,20 +49,14 @@ void PvdWriter<W>
template <class W>
void PvdWriter<W>
::write (std::string const& fn) const
::write (std::string const& fn, Std::optional<std::string> /*dir*/) const
{
auto p = filesystem::path(fn);
auto name = p.stem();
p.remove_filename();
p /= name.string();
int rank = 0;
int num_ranks = 1;
#ifdef HAVE_MPI
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &num_ranks);
#endif
int rank = vtkWriter_.rank_;
if (rank == 0) {
std::ofstream out(p.string() + ".pvd", std::ios_base::ate | std::ios::binary);
assert(out.is_open());
......
......@@ -58,16 +58,22 @@ namespace Dune
* \param fn Filename of the file to write to. Only the base part
* (without dir and extentsion) is used to write the intermediate
* file into a tmp directory.
* \param tmpDir If the directory is given, it is used as tmp dir, otherwise /tmp.
* \param writeCollection Create a timeseries file directly
**/
void writeTimestep (double time, std::string const& fn, bool writeCollection = true) const;
void writeTimestep (double time, std::string const& fn,
Std::optional<std::string> tmpDir = {},
bool writeCollection = true) const;
/// Writes all timesteps to single timeseries file.
// NOTE: requires an aforging call to \ref writeTimestep
/**
* Create a timeseries file with all timesteps written by \ref writeTimestep.
*
* \param fn Filename of the Timeseries file. May contain a directory and any file extension.
* \param dir The optional parameter specifies the directory of the partition files.
**/
virtual void write (std::string const& fn) const override;
virtual void write (std::string const& fn, Std::optional<std::string> dir = {}) const override;
/// Attach point data to the writer, \see VtkFunction for possible arguments
template <class Function, class... Args>
......
......@@ -9,7 +9,7 @@
#include <sstream>
#include <string>
#ifdef HAVE_ZLIB
#if HAVE_ZLIB
#include <zlib.h>
#endif
......@@ -39,24 +39,20 @@ VtkTimeseriesWriter<W>::~VtkTimeseriesWriter ()
template <class W>
void VtkTimeseriesWriter<W>
::writeTimestep (double time, std::string const& fn, bool writeCollection) const
::writeTimestep (double time, std::string const& fn, Std::optional<std::string> tmpDir, bool writeCollection) const
{
auto name = filesystem::path(fn).stem();
auto tmp = tmpDir_;
auto tmp = tmpDir ? filesystem::path(*tmpDir) : tmpDir_;
tmp /= name.string();
vtkWriter_.dataCollector_.update();
std::string filenameBase = tmp.string();
int rank = 0;
int num_ranks = 1;
#ifdef HAVE_MPI
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &num_ranks);
if (num_ranks > 1)
filenameBase = tmp.string() + "_p" + std::to_string(rank);
#endif
int rank = vtkWriter_.rank_;
int numRanks = vtkWriter_.numRanks_;
if (numRanks > 1)
filenameBase = tmp.string() + "_p" + std::to_string(rank);
if (!initialized_) {
// write points and cells only once
......@@ -78,28 +74,29 @@ void VtkTimeseriesWriter<W>
template <class W>
void VtkTimeseriesWriter<W>
::write (std::string const& fn) const
::write (std::string const& fn, Std::optional<std::string> dir) const
{
assert( initialized_ );
auto p = filesystem::path(fn);
auto name = p.stem();
p.remove_filename();
p /= name.string();
std::string filename = p.string() + "_ts";
filesystem::path fn_dir = p;
filesystem::path data_dir = dir ? filesystem::path(*dir) : fn_dir;
filesystem::path rel_dir = filesystem::relative(data_dir, fn_dir);
int rank = 0;
int num_ranks = 1;
#ifdef HAVE_MPI
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &num_ranks);
if (num_ranks > 1)
filename = p.string() + "_ts_p" + std::to_string(rank);
#endif
std::string serial_fn = fn_dir.string() + '/' + name.string() + "_ts";
std::string parallel_fn = data_dir.string() + '/' + name.string() + "_ts";
std::string rel_fn = rel_dir.string() + '/' + name.string() + "_ts";
int rank = vtkWriter_.rank_;
int numRanks = vtkWriter_.numRanks_;
if (numRanks > 1)
serial_fn += "_p" + std::to_string(rank);
{ // write serial file
std::ofstream serial_out(filename + "." + vtkWriter_.getFileExtension(),
std::ofstream serial_out(serial_fn + "." + vtkWriter_.getFileExtension(),
std::ios_base::ate | std::ios::binary);
assert(serial_out.is_open());
......@@ -111,10 +108,9 @@ void VtkTimeseriesWriter<W>
vtkWriter_.writeTimeseriesSerialFile(serial_out, filenameMesh_, timesteps_, blocks_);
}
#ifdef HAVE_MPI
if (num_ranks > 1 && rank == 0) {
if (numRanks > 1 && rank == 0) {
// write parallel file
std::ofstream parallel_out(p.string() + "_ts.p" + vtkWriter_.getFileExtension(),
std::ofstream parallel_out(parallel_fn + ".p" + vtkWriter_.getFileExtension(),
std::ios_base::ate | std::ios::binary);
assert(parallel_out.is_open());
......@@ -123,9 +119,8 @@ void VtkTimeseriesWriter<W>
? std::numeric_limits<float>::digits10+2
: std::numeric_limits<double>::digits10+2);
vtkWriter_.writeTimeseriesParallelFile(parallel_out, p.string() + "_ts", num_ranks, timesteps_);
vtkWriter_.writeTimeseriesParallelFile(parallel_out, rel_fn, numRanks, timesteps_);
}
#endif
}
} // end namespace Dune
......@@ -44,10 +44,12 @@ namespace Dune
Vtk::FormatTypes format = Vtk::BINARY,
Vtk::DataTypes datatype = Vtk::FLOAT32)
: dataCollector_(gridView)
, rank_(gridView.comm().rank())
, numRanks_(gridView.comm().size())
, format_(format)
, datatype_(datatype)
{
#ifndef HAVE_ZLIB
#if !HAVE_ZLIB
if (format_ == Vtk::COMPRESSED) {
std::cout << "Dune is compiled without compression. Falling back to BINARY VTK output!\n";
format_ = Vtk::BINARY;
......@@ -56,7 +58,11 @@ namespace Dune
}
/// Write the attached data to the file
virtual void write (std::string const& fn) const override;
/**
* \param fn Filename of the VTK file. May contain a directory and any file extension.
* \param dir The optional parameter specifies the directory of the partition files.
**/
virtual void write (std::string const& fn, Std::optional<std::string> dir = {}) const override;
/// Attach point data to the writer, \see VtkFunction for possible arguments
template <class Function, class... Args>
......@@ -151,6 +157,10 @@ namespace Dune
protected:
mutable DataCollector dataCollector_;
// the rank and size of the gridView collective communication
int rank_ = 0;
int numRanks_ = 1;
Vtk::FormatTypes format_;
Vtk::DataTypes datatype_;
......
......@@ -8,7 +8,7 @@
#include <sstream>
#include <string>
#ifdef HAVE_ZLIB
#if HAVE_ZLIB
#include <zlib.h>
#endif
......@@ -23,29 +23,27 @@ namespace Dune {
template <class GV, class DC>
void VtkWriterInterface<GV,DC>
::write (std::string const& fn) const
::write (std::string const& fn, Std::optional<std::string> dir) const
{
dataCollector_.update();
auto p = filesystem::path(fn);
auto name = p.stem();
p.remove_filename();
p /= name.string();
std::string filename = p.string();
filesystem::path fn_dir = p;
filesystem::path data_dir = dir ? filesystem::path(*dir) : fn_dir;
filesystem::path rel_dir = filesystem::relative(data_dir, fn_dir);
int rank = 0;
int num_ranks = 1;
std::string serial_fn = fn_dir.string() + '/' + name.string();
std::string parallel_fn = data_dir.string() + '/' + name.string();
std::string rel_fn = rel_dir.string() + '/' + name.string();
#ifdef HAVE_MPI
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &num_ranks);
if (num_ranks > 1)
filename = p.string() + "_p" + std::to_string(rank);
#endif
if (numRanks_ > 1)
serial_fn += "_p" + std::to_string(rank_);
{ // write serial file
std::ofstream serial_out(filename + "." + fileExtension(), std::ios_base::ate | std::ios::binary);
std::ofstream serial_out(serial_fn + "." + fileExtension(), std::ios_base::ate | std::ios::binary);
assert(serial_out.is_open());
serial_out.imbue(std::locale::classic());
......@@ -56,10 +54,9 @@ void VtkWriterInterface<GV,DC>
writeSerialFile(serial_out);
}
#ifdef HAVE_MPI
if (num_ranks > 1 && rank == 0) {
if (numRanks_ > 1 && rank_ == 0) {
// write parallel file
std::ofstream parallel_out(p.string() + ".p" + fileExtension(), std::ios_base::ate | std::ios::binary);
std::ofstream parallel_out(parallel_fn + ".p" + fileExtension(), std::ios_base::ate | std::ios::binary);
assert(parallel_out.is_open());
parallel_out.imbue(std::locale::classic());
......@@ -67,9 +64,8 @@ void VtkWriterInterface<GV,DC>
? std::numeric_limits<float>::digits10+2
: std::numeric_limits<double>::digits10+2);
writeParallelFile(parallel_out, p.string(), num_ranks);
writeParallelFile(parallel_out, rel_fn, numRanks_);
}
#endif
}
......@@ -220,7 +216,7 @@ template <class OStream>
std::uint64_t writeCompressed (unsigned char const* buffer, unsigned char* buffer_out,
std::uint64_t bs, std::uint64_t cbs, int level, OStream& outb)
{
#ifdef HAVE_ZLIB
#if HAVE_ZLIB
uLongf uncompressed_space = uLongf(bs);
uLongf compressed_space = uLongf(cbs);
......
......@@ -34,7 +34,7 @@ void write (std::string prefix, GridView const& gridView)
seriesWriter.addCellData(p1Analytic, "q0");
std::string filename = prefix + "_" + std::to_string(GridView::dimensionworld) + "d_binary32.vtu";
for (double t = 0.0; t < 5; t += 0.5) {
seriesWriter.writeTimestep(t, filename, false);
seriesWriter.writeTimestep(t, filename, {}, false);
shift += 0.25;
}
seriesWriter.write(filename);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment