Commit afca0d76 authored by Simon Praetorius's avatar Simon Praetorius
Browse files

Put all classes into the Vtk namespace

parent f228be09
Pipeline #31807 failed with stage
in 0 seconds
......@@ -12,7 +12,7 @@ Please see the [general instructions for building DUNE modules](https://www.dune
for detailed instructions on how to build the module.
## Usage
The VTK writer works similar to the dune-grid `VTKWriter`. It needs to be bound
The Vtk writer works similar to the dune-grid `VTKWriter`. It needs to be bound
to a GridView and then data can be added to the points or cells in the grid.
Points are not necessarily grid vertices, but any coordinates placed inside the
grid cells, so the data must be provided as GridViewFunction to allow the local
......@@ -37,13 +37,13 @@ public:
```
where `Function` is either a `GridViewFunction`, i.e. supports `bind()`, `unbind()`, and `localFunction(Function)`, or is a legacy `VTKFunction` from Dune-Grid. The optional parameters `name`, `numComponents` and `format` may be given for a `GridViewFunction`.
The parameter `Vtk::FormatTypes` is one of `Vtk::ASCII`, `Vtk::BINARY`, or `Vtk::COMPRESSED` and `Vtk::DataTypes` is one of `Vtk::FLOAT32`, or `Vtk::FLOAT64`. The `[Type]` of a VtkWriter is one of `UnstructuredGrid`, `StructuredGrid`, `RectilinearGrid`, `ImageData`, or `Timeseries`, see below for details. A `DataCollector` may be specified to control how point and cell values are extracted from the `GridView` and the bound data. See `dune/vtk/datacollectors/` of a list of poissible types. The default datacollector extracts a connected grid with continuous data, where points are grid vertices.
The parameter `Vtk::FormatTypes` is one of `Vtk::ASCII`, `Vtk::BINARY`, or `Vtk::COMPRESSED` and `Vtk::DataTypes` is one of `Vtk::FLOAT32`, or `Vtk::FLOAT64`. The `[Type]` of a VtkWriter is one of `UnstructuredGrid`, `StructuredGrid`, `RectilinearGrid`, `ImageData`, or `Timeseries`, see below for details. A `DataCollector` may be specified to control how point and cell values are extracted from the `GridView` and the bound data. See `dune/vtk/datacollectors/` of a list of possible types. The default datacollector extracts a connected grid with continuous data, where points are grid vertices.
See also the `src/` directory for more examples.
## Comparison with Dune::VTKWriter
In Dune-Grid there is a VTK writer available, that is a bit different from the
proposed one. A comparions:
proposed one. A comparison:
| **Property** | **Dune-Grid** | **Dune-Vtk** |
| ------------------ | :-----------: | :----------: |
......
......@@ -11,75 +11,78 @@
namespace Dune
{
/// File-Writer for ParaView .pvd files
template <class VtkWriter>
class PvdWriter
: public Vtk::FileWriter
namespace Vtk
{
using Self = PvdWriter;
public:
/// Constructor, creates a VtkWriter with constructor arguments forwarded
template <class... Args,
disableCopyMove<Self,Args...> = 0>
explicit PvdWriter (Args&&... args)
: vtkWriter_{std::forward<Args>(args)...}
/// File-Writer for ParaView .pvd files
template <class VtkWriter>
class PvdWriter
: public Vtk::FileWriter
{
format_ = vtkWriter_.getFormat();
datatype_ = vtkWriter_.getDatatype();
}
using Self = PvdWriter;
/// \brief Write the attached data to the file
/**
* 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 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, std::optional<std::string> dir = {},
bool writeCollection = true) const;
public:
/// Constructor, creates a VtkWriter with constructor arguments forwarded
template <class... Args,
disableCopyMove<Self,Args...> = 0>
explicit PvdWriter (Args&&... args)
: vtkWriter_{std::forward<Args>(args)...}
{
format_ = vtkWriter_.getFormat();
datatype_ = vtkWriter_.getDatatype();
}
/// \brief Writes collection of timesteps to .pvd file.
// NOTE: requires an aforgoing call to \ref writeTimestep
/**
* \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 std::string write (std::string const& fn, std::optional<std::string> dir = {}) const override;
/// \brief Write the attached data to the file
/**
* 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 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, std::optional<std::string> dir = {},
bool writeCollection = true) const;
/// Attach point data to the writer, \see Vtk::Function for possible arguments
template <class Function, class... Args>
PvdWriter& addPointData (Function const& fct, Args&&... args)
{
vtkWriter_.addPointData(fct, std::forward<Args>(args)...);
return *this;
}
/// \brief Writes collection of timesteps to .pvd file.
// NOTE: requires an aforgoing call to \ref writeTimestep
/**
* \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 std::string write (std::string const& fn, std::optional<std::string> dir = {}) const override;
/// Attach cell data to the writer, \see Vtk::Function for possible arguments
template <class Function, class... Args>
PvdWriter& addCellData (Function const& fct, Args&&... args)
{
vtkWriter_.addCellData(fct, std::forward<Args>(args)...);
return *this;
}
/// Attach point data to the writer, \see Vtk::Function for possible arguments
template <class Function, class... Args>
PvdWriter& addPointData (Function const& fct, Args&&... args)
{
vtkWriter_.addPointData(fct, std::forward<Args>(args)...);
return *this;
}
/// Attach cell data to the writer, \see Vtk::Function for possible arguments
template <class Function, class... Args>
PvdWriter& addCellData (Function const& fct, Args&&... args)
{
vtkWriter_.addCellData(fct, std::forward<Args>(args)...);
return *this;
}
protected:
/// Write a series of vtk files in a .pvd ParaView Data file
void writeFile (std::ofstream& out) const;
protected:
/// Write a series of vtk files in a .pvd ParaView Data file
void writeFile (std::ofstream& out) const;
protected:
VtkWriter vtkWriter_;
Vtk::FormatTypes format_;
Vtk::DataTypes datatype_;
protected:
VtkWriter vtkWriter_;
Vtk::FormatTypes format_;
Vtk::DataTypes datatype_;
mutable std::vector<std::pair<double, std::string>> timesteps_;
};
mutable std::vector<std::pair<double, std::string>> timesteps_;
};
} // end namespace Vtk
} // end namespace Dune
#include "pvdwriter.impl.hh"
......@@ -7,6 +7,7 @@
#include <dune/vtk/utility/string.hh>
namespace Dune {
namespace Vtk {
template <class W>
void PvdWriter<W>
......@@ -104,4 +105,5 @@ void PvdWriter<W>
out << "</VTKFile>";
}
} // end namespace Vtk
} // end namespace Dune
......@@ -20,6 +20,7 @@
int main (int argc, char** argv)
{
using namespace Dune;
using namespace Dune::Vtk;
MPIHelper::instance(argc, argv);
auto grid = StructuredGridFactory<GridType>::createCubeGrid({0.0,0.0}, {1.0,2.0}, {2u,4u});
......@@ -28,7 +29,7 @@ int main (int argc, char** argv)
VtkUnstructuredGridWriter writer1(grid->leafGridView());
// 2. construct writer from datacollector
Vtk::ContinuousDataCollector dataCollector1(grid->leafGridView());
ContinuousDataCollector dataCollector1(grid->leafGridView());
VtkUnstructuredGridWriter writer2(dataCollector1);
VtkUnstructuredGridWriter writer3(stackobject_to_shared_ptr(dataCollector1));
......@@ -40,6 +41,6 @@ int main (int argc, char** argv)
VtkReader reader1(factory);
// 5. construct reader from grid-creator
Vtk::ContinuousGridCreator creator(factory);
ContinuousGridCreator creator(factory);
VtkReader reader2(creator);
}
\ No newline at end of file
}
......@@ -43,35 +43,38 @@ struct Acc
template <class GridView>
int testGridView (std::string prefix, Dune::VTKChecker& vtkChecker, GridView const& gridView)
{
using namespace Dune;
using namespace Vtk;
enum { dim = GridView :: dimension };
Dune::VtkWriter<GridView> vtk(gridView);
VtkWriter<GridView> vtk(gridView);
auto f1 = Dune::Functions::makeAnalyticGridViewFunction([](const auto& x) { return std::sin(x.two_norm()); },gridView);
auto f1 = Functions::makeAnalyticGridViewFunction([](const auto& x) { return std::sin(x.two_norm()); },gridView);
vtk.addCellData(f1, "scalar-valued lambda");
auto f2 = Dune::Functions::makeAnalyticGridViewFunction([](const auto& x) { return x; },gridView);
auto f2 = Functions::makeAnalyticGridViewFunction([](const auto& x) { return x; },gridView);
vtk.addPointData(f2, "vector-valued lambda");
int result = 0;
// ASCII files
{
vtk.setFormat(Dune::Vtk::ASCII);
vtk.setFormat(ASCII);
std::string name = vtk.write(prefix + "_ascii");
if (gridView.comm().rank() == 0) vtkChecker.push(name);
}
// BINARY files
{
vtk.setFormat(Dune::Vtk::BINARY);
vtk.setFormat(BINARY);
std::string name = vtk.write(prefix + "_binary");
if (gridView.comm().rank() == 0) vtkChecker.push(name);
}
// COMPRESSED files
{
vtk.setFormat(Dune::Vtk::COMPRESSED);
vtk.setFormat(COMPRESSED);
std::string name = vtk.write(prefix + "_compressed");
if (gridView.comm().rank() == 0) vtkChecker.push(name);
}
......
......@@ -7,10 +7,12 @@
* \brief Macro for wrapping error checks and throwing exceptions
*/
namespace Dune {
class VtkError : public Exception {};
namespace Dune
{
namespace Vtk
{
class VtkError : public Exception {};
}
}
/**
......@@ -19,7 +21,7 @@ class VtkError : public Exception {};
#define VTK_ASSERT_MSG(cond, text) \
do { \
if (!(cond)) \
DUNE_THROW(Dune::VtkError, text); \
DUNE_THROW(Dune::Vtk::VtkError, text); \
} while (false)
......@@ -29,5 +31,5 @@ class VtkError : public Exception {};
#define VTK_ASSERT(cond) \
do { \
if (!(cond)) \
DUNE_THROW(Dune::VtkError, #cond); \
DUNE_THROW(Dune::Vtk::VtkError, #cond); \
} while (false)
......@@ -22,7 +22,7 @@
* topologies up to 4d are tested. Note, this may lead to prolonged
* compiler runs.
*
* For debugging purpuse the functions and the derivatives can be
* For debugging purpose the functions and the derivatives can be
* printed. You have to define the macro TEST_OUTPUT_FUNCTIONS to
* activate this function.
*/
......@@ -75,8 +75,8 @@ bool test(const Basis &basis, const Points &points, bool verbose)
template <class Topology>
bool test(unsigned int order, bool verbose = false)
{
typedef Dune::LagrangeBasisFactory<Dune::Vtk::LagrangePointSet,Topology::dimension,StorageField,ComputeField> BasisFactory;
typedef Dune::LagrangeCoefficientsFactory< Dune::Vtk::LagrangePointSet, Topology::dimension,double > LagrangeCoefficientsFactory;
typedef Dune::LagrangeBasisFactory<Dune::Vtk::LagrangePointSet, Topology::dimension, StorageField, ComputeField> BasisFactory;
typedef Dune::LagrangeCoefficientsFactory<Dune::Vtk::LagrangePointSet, Topology::dimension, double> LagrangeCoefficientsFactory;
bool ret = true;
......
......@@ -18,254 +18,257 @@
namespace Dune
{
/// File-Reader for Vtk unstructured .vtu files
/**
* Reads .vtu files and constructs a grid from the cells stored in the file
* Additionally, stored data can be read.
*
* NOTE: Assumption on the file structure: Each XML tag must be on a separate line.
*
* \tparam Grid The type of the grid to construct.
* \tparam GridCreator Policy type to control what to pass to a grid factory with
* data given from the file. [ContinuousGridCreator]
* \tparam FieldType Type of the components of the data to extract from the file [default: double]
**/
template <class Grid, class GridCreator = Vtk::ContinuousGridCreator<Grid>, class FieldType = double>
class VtkReader
: public Vtk::FileReader<Grid, VtkReader<Grid, GridCreator>>
namespace Vtk
{
// Sections visited during the xml parsing
enum Sections {
NO_SECTION = 0, VTK_FILE, UNSTRUCTURED_GRID, PIECE, POINT_DATA, PD_DATA_ARRAY, CELL_DATA, CD_DATA_ARRAY,
POINTS, POINTS_DATA_ARRAY, CELLS, CELLS_DATA_ARRAY, APPENDED_DATA, XML_NAME, XML_NAME_ASSIGN, XML_VALUE
};
// Type storing information about read data
struct DataArrayAttributes
{
Vtk::DataTypes type;
unsigned int components = 1;
std::uint64_t offset = 0;
Sections section = NO_SECTION;
};
// Type of global world coordinates
using GlobalCoordinate = typename GridCreator::GlobalCoordinate;
// Template representing a grid-function that is created in getPointData() and getCellData()
// with Context either Vtk::PointContext or Vek::CellContext, respectively.
// To each GridCreate a GridFunction is associated, see, e.g. Vtk::ContinuousGridFunction
// or Vtk::LagrangeGridFunction.
template <class Context>
using GridFunction = typename Vtk::AssociatedGridFunction<GridCreator, FieldType, Context>::type;
public:
/// Constructor. Creates a new GridCreator with the passed factory
template <class... Args,
std::enable_if_t<std::is_constructible<GridCreator, Args...>::value,int> = 0>
explicit VtkReader (Args&&... args)
: VtkReader(std::make_shared<GridCreator>(std::forward<Args>(args)...))
{}
/// Constructor. Stores the references in a non-destroying shared_ptr
explicit VtkReader (GridCreator& creator)
: VtkReader(stackobject_to_shared_ptr(creator))
{}
/// Constructor. Stores the shared_ptr
explicit VtkReader (std::shared_ptr<GridCreator> creator)
: creator_(std::move(creator))
{}
/// Read the grid from file with `filename` into the GridCreator
/// File-Reader for Vtk unstructured .vtu files
/**
* This function fills internal data containers representing the information from the
* passed file.
*
* \param filename The name of the input file
* \param fillCreator If `false`, only fill internal data structures, if `true`, pass
* the internal data to the GridCreator. [true]
**/
void read (std::string const& filename, bool fillCreator = true);
/// Obtains the creator of the reader
GridCreator& gridCreator ()
* Reads .vtu files and constructs a grid from the cells stored in the file
* Additionally, stored data can be read.
*
* NOTE: Assumption on the file structure: Each XML tag must be on a separate line.
*
* \tparam Grid The type of the grid to construct.
* \tparam GridCreator Policy type to control what to pass to a grid factory with
* data given from the file. [ContinuousGridCreator]
* \tparam FieldType Type of the components of the data to extract from the file [default: double]
**/
template <class Grid, class GridCreator = Vtk::ContinuousGridCreator<Grid>, class FieldType = double>
class VtkReader
: public Vtk::FileReader<Grid, VtkReader<Grid, GridCreator>>
{
return *creator_;
}
// Sections visited during the xml parsing
enum Sections {
NO_SECTION = 0, VTK_FILE, UNSTRUCTURED_GRID, PIECE, POINT_DATA, PD_DATA_ARRAY, CELL_DATA, CD_DATA_ARRAY,
POINTS, POINTS_DATA_ARRAY, CELLS, CELLS_DATA_ARRAY, APPENDED_DATA, XML_NAME, XML_NAME_ASSIGN, XML_VALUE
};
// Type storing information about read data
struct DataArrayAttributes
{
Vtk::DataTypes type;
unsigned int components = 1;
std::uint64_t offset = 0;
Sections section = NO_SECTION;
};
// Type of global world coordinates
using GlobalCoordinate = typename GridCreator::GlobalCoordinate;
// Template representing a grid-function that is created in getPointData() and getCellData()
// with Context either Vtk::PointContext or Vek::CellContext, respectively.
// To each GridCreate a GridFunction is associated, see, e.g. Vtk::ContinuousGridFunction
// or Vtk::LagrangeGridFunction.
template <class Context>
using GridFunction = typename Vtk::AssociatedGridFunction<GridCreator, FieldType, Context>::type;
public:
/// Constructor. Creates a new GridCreator with the passed factory
template <class... Args,
std::enable_if_t<std::is_constructible<GridCreator, Args...>::value,int> = 0>
explicit VtkReader (Args&&... args)
: VtkReader(std::make_shared<GridCreator>(std::forward<Args>(args)...))
{}
/// Constructor. Stores the references in a non-destroying shared_ptr
explicit VtkReader (GridCreator& creator)
: VtkReader(stackobject_to_shared_ptr(creator))
{}
/// Constructor. Stores the shared_ptr
explicit VtkReader (std::shared_ptr<GridCreator> creator)
: creator_(std::move(creator))
{}
/// Read the grid from file with `filename` into the GridCreator
/**
* This function fills internal data containers representing the information from the
* passed file.
*
* \param filename The name of the input file
* \param fillCreator If `false`, only fill internal data structures, if `true`, pass
* the internal data to the GridCreator. [true]
**/
void read (std::string const& filename, bool fillCreator = true);
/// Obtains the creator of the reader
GridCreator& gridCreator ()
{
return *creator_;
}
/// Construct the actual grid using the GridCreator
/// NOTE: requires an aforgoing call to \ref read()
std::unique_ptr<Grid> createGrid () const
{
return creator_->createGrid();
}
/// Construct a grid-function representing the point-data with the given name
/// NOTE: requires an aforgoing call to \ref read()
GridFunction<Vtk::PointContext> getPointData (std::string const& name) const
{
auto const& data = dataArray_.at(name);
VTK_ASSERT_MSG(data.section == POINT_DATA,
"The data to extract is not point-data. Use `getCellData()` instead!");
return {*creator_, pointData_.at(name), data.components,
vec_types, vec_offsets, vec_connectivity};
}
/// Construct a grid-function representing the cell-data with the given name
/// NOTE: requires an aforgoing call to \ref read()
GridFunction<Vtk::CellContext> getCellData (std::string const& name) const
{
auto const& data = dataArray_.at(name);
VTK_ASSERT_MSG(data.section == CELL_DATA,
"The data to extract is not cell-data. Use `getPointData()` instead!");
return {*creator_, cellData_.at(name), data.components,
vec_types, vec_offsets, vec_connectivity};
}
/// Advanced read methods
/// @{
/// Read the grid from an input stream, referring to a .vtu file, into the GridFactory \ref factory_
/**
* \param input A STL input stream to read the VTK file from.
* \param create If `false`, only fill internal data structures, if `true`, also create the grid. [true]
**/
void readSerialFileFromStream (std::ifstream& input, bool create = true);
/// Read the grid from and input stream, referring to a .pvtu file, into the GridFactory \ref factory_
/**
* \param input A STL input stream to read the VTK file from.
* \param create If `false`, only fill internal data structures, if `true`, also create the grid. [true]
**/
void readParallelFileFromStream (std::ifstream& input, int rank, int size, bool create = true);
/// Insert all internal data to the GridCreator
/// NOTE: requires an aforgoing call to \ref read()
void fillGridCreator (bool insertPieces = true);
/// @}
/// Return the filenames of parallel pieces
std::vector<std::string> const& pieces () const
{
return pieces_;
}
#ifndef DOXYGEN
// Implementation of the FileReader interface
static void fillFactoryImpl (GridFactory<Grid>& factory, std::string const& filename)
{
VtkReader reader{factory};
reader.read(filename);
}
#endif
private:
// Read values stored on the cells with name `name`
Sections readCellData (std::ifstream& /*input*/, std::string /*name*/);
template <class T>
void readCellDataAppended (std::ifstream& /*input*/, std::string /*name*/);
// Read values stored on the points with name `name`
Sections readPointData (std::ifstream& /*input*/, std::string /*name*/);
template <class T>
void readPointDataAppended (std::ifstream& /*input*/, std::string /*name*/);
// Read vertex coordinates from `input` stream and store in into `factory`
Sections readPoints (std::ifstream& input, std::string name);
template <class T>
void readPointsAppended (std::ifstream& input);
// Read cell type, cell offsets and connectivity from `input` stream
Sections readCells (std::ifstream& input, std::string name);
void readCellsAppended (std::ifstream& input);
// Read data from appended section in vtk file, starting from `offset`
template <class T>
void readAppended (std::ifstream& input, std::vector<T>& values, std::uint64_t offset);
// Test whether line belongs to section
bool isSection (std::string line,
std::string key,
Sections current,
Sections parent = NO_SECTION) const
{
bool result = line.substr(1, key.length()) == key;
if (result && current != parent)
DUNE_THROW(Exception , "<" << key << "> in wrong section." );
return result;
}
// Find beginning of appended binary data
std::uint64_t findAppendedDataPosition (std::ifstream& input) const;
/// Construct the actual grid using the GridCreator
/// NOTE: requires an aforgoing call to \ref read()
std::unique_ptr<Grid> createGrid () const
{
return creator_->createGrid();
}
/// Construct a grid-function representing the point-data with the given name
/// NOTE: requires an aforgoing call to \ref read()
GridFunction<Vtk::PointContext> getPointData (std::string const& name) const
{
auto const& data = dataArray_.at(name);
VTK_ASSERT_MSG(data.section == POINT_DATA,
"The data to extract is not point-data. Use `getCellData()` instead!");
return {*creator_, pointData_.at(name), data.components,
vec_types, vec_offsets, vec_connectivity};
}
/// Construct a grid-function representing the cell-data with the given name
/// NOTE: requires an aforgoing call to \ref read()
GridFunction<Vtk::CellContext> getCellData (std::string const& name) const
{
auto const& data = dataArray_.at(name);
VTK_ASSERT_MSG(data.section == CELL_DATA,
"The data to extract is not cell-data. Use `getPointData()` instead!");
// Read attributes from current xml tag
std::map<std::string, std::string> parseXml (std::string const& line, bool& closed);
return {*creator_, cellData_.at(name), data.components,
vec_types, vec_offsets, vec_connectivity};
}
// clear all vectors
void clear ();
/// Advanced read methods
/// @{
/// Read the grid from an input stream, referring to a .vtu file, into the GridFactory \ref factory_
/**
* \param input A STL input stream to read the VTK file from.
* \param create If `false`, only fill internal data structures, if `true`, also create the grid. [true]
**/