diff --git a/dumux/io/vtkoutputmodule.hh b/dumux/io/vtkoutputmodule.hh index 47ff05309160367b89e7799eaa7d8cb58113fa54..be8bab380eb4019bbcfad3c81af6fa32797d940e 100644 --- a/dumux/io/vtkoutputmodule.hh +++ b/dumux/io/vtkoutputmodule.hh @@ -242,6 +242,11 @@ class VtkOutputModule public: + enum class FieldType : unsigned int + { + element, vertex, automatic + }; + VtkOutputModule(const Problem& problem, const FVGridGeometry& fvGridGeometry, const GridVariables& gridVariables, @@ -281,19 +286,51 @@ public: volVarScalarDataInfo_.push_back(VolVarScalarDataInfo{f, name}); } - //! Add a scalar or vector valued field - //! \param v The scalar field to be added - //! \param name The name of the vtk field - //! \param nComp Number of components of the vector (maximum 3) + //! Add a scalar or vector valued vtk field + //! \param v The field to be added. Can be any indexable container. Its value type can be a number or itself an indexable container. + //! \param name The name of the field + //! \param fieldType The type of the field. + //! This determines whether the values are associated with vertices or elements. + //! By default, the method automatically deduces the correct type for the given input. template<typename Vector> - void addField(const Vector& v, const std::string& name, int nComp = 1) + void addField(const Vector& v, const std::string& name, FieldType fieldType = FieldType::automatic) { - if (v.size() == gridGeom_.gridView().size(0)) + // Deduce the number of components from the given vector type + const auto nComp = getNumberOfComponents_(v); + + const auto numElements = gridGeom_.gridView().size(0); + const auto numVertices = gridGeom_.gridView().size(dim); + + // Automatically deduce the field type ... + if(fieldType == FieldType::automatic) + { + if(numElements == numVertices) + DUNE_THROW(Dune::InvalidStateException, "Automatic deduction of FieldType failed. Please explicitly specify FieldType::element or FieldType::vertex."); + + if(v.size() == numElements) + fieldType = FieldType::element; + else if(v.size() == numVertices) + fieldType = FieldType::vertex; + else + DUNE_THROW(Dune::RangeError, "Size mismatch of added field!"); + } + // ... or check if the user-specified type matches the size of v + else + { + if(fieldType == FieldType::element) + if(v.size() != numElements) + DUNE_THROW(Dune::RangeError, "Size mismatch of added field!"); + + if(fieldType == FieldType::vertex) + if(v.size() != numVertices) + DUNE_THROW(Dune::RangeError, "Size mismatch of added field!"); + } + + // add the appropriate field + if (fieldType == FieldType::element) fields_.emplace_back(gridGeom_.gridView(), gridGeom_.elementMapper(), v, name, nComp, 0); - else if (v.size() == gridGeom_.gridView().size(dim)) - fields_.emplace_back(gridGeom_.gridView(), gridGeom_.vertexMapper(), v, name, nComp, dim); else - DUNE_THROW(Dune::RangeError, "Size mismatch of added field!"); + fields_.emplace_back(gridGeom_.gridView(), gridGeom_.vertexMapper(), v, name, nComp, dim); } ////////////////////////////////////////////////////////////////////////////////////////////// @@ -458,6 +495,15 @@ public: } private: + //! Deduces the number of components of the value type of a vector of values + template<class Vector, typename std::enable_if_t<Dune::is_indexable<decltype(std::declval<Vector>()[0])>::value, int> = 0> + std::size_t getNumberOfComponents_(const Vector& v) + { return v[0].size(); } + + //! Deduces the number of components of the value type of a vector of values + template<class Vector, typename std::enable_if_t<!Dune::is_indexable<decltype(std::declval<Vector>()[0])>::value, int> = 0> + std::size_t getNumberOfComponents_(const Vector& v) + { return 1; } template<typename Writer, typename... Args> void addDofDataForWriter_(Writer& writer, diff --git a/test/freeflow/staggered/test_angeli.cc b/test/freeflow/staggered/test_angeli.cc index 7e53402957abacfbc5c9aa7eec866b6468713f83..6b7f620176f352d38c7ffe061fcab9d55a31e1c7 100644 --- a/test/freeflow/staggered/test_angeli.cc +++ b/test/freeflow/staggered/test_angeli.cc @@ -141,7 +141,6 @@ int main(int argc, char** argv) try problem->setTimeLoop(timeLoop); // the solution vector - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); using DofTypeIndices = typename GET_PROP(TypeTag, DofTypeIndices); typename DofTypeIndices::CellCenterIdx cellCenterIdx; @@ -163,8 +162,8 @@ int main(int argc, char** argv) try using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); StaggeredVtkOutputModule<TypeTag> vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); VtkOutputFields::init(vtkWriter); //! Add model specific output fields - vtkWriter.addField(problem->getAnalyticalPressureSolution(), "pressureExact", 1); - vtkWriter.addField(problem->getAnalyticalVelocitySolution(), "velocityExact", GridView::dimensionworld); + vtkWriter.addField(problem->getAnalyticalPressureSolution(), "pressureExact"); + vtkWriter.addField(problem->getAnalyticalVelocitySolution(), "velocityExact"); vtkWriter.addFaceField(problem->getAnalyticalVelocitySolutionOnFace(), "faceVelocityExact"); vtkWriter.write(0.0); diff --git a/test/freeflow/staggered/test_donea.cc b/test/freeflow/staggered/test_donea.cc index ca8684a1198d40aabb2ac2d25a434a236dcef8b2..173b09a2c3c3a2a9c61164fdf3fb77650b614042 100644 --- a/test/freeflow/staggered/test_donea.cc +++ b/test/freeflow/staggered/test_donea.cc @@ -125,7 +125,6 @@ int main(int argc, char** argv) try auto problem = std::make_shared<Problem>(fvGridGeometry); // the solution vector - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); using DofTypeIndices = typename GET_PROP(TypeTag, DofTypeIndices); typename DofTypeIndices::CellCenterIdx cellCenterIdx; @@ -159,8 +158,8 @@ int main(int argc, char** argv) try using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); StaggeredVtkOutputModule<TypeTag> vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); VtkOutputFields::init(vtkWriter); //! Add model specific output fields - vtkWriter.addField(problem->getAnalyticalPressureSolution(), "pressureExact", 1); - vtkWriter.addField(problem->getAnalyticalVelocitySolution(), "velocityExact", GridView::dimensionworld); + vtkWriter.addField(problem->getAnalyticalPressureSolution(), "pressureExact"); + vtkWriter.addField(problem->getAnalyticalVelocitySolution(), "velocityExact"); vtkWriter.addFaceField(problem->getAnalyticalVelocitySolutionOnFace(), "faceVelocityExact"); vtkWriter.write(0.0); diff --git a/test/freeflow/staggered/test_kovasznay.cc b/test/freeflow/staggered/test_kovasznay.cc index 16f5b81f7e7227f40419be6076a735d5e422c8df..b1c855a136d9605751c732f73eb91d507b87fd47 100644 --- a/test/freeflow/staggered/test_kovasznay.cc +++ b/test/freeflow/staggered/test_kovasznay.cc @@ -124,7 +124,6 @@ int main(int argc, char** argv) try auto problem = std::make_shared<Problem>(fvGridGeometry); // the solution vector - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); using DofTypeIndices = typename GET_PROP(TypeTag, DofTypeIndices); typename DofTypeIndices::CellCenterIdx cellCenterIdx; @@ -158,8 +157,8 @@ int main(int argc, char** argv) try using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); StaggeredVtkOutputModule<TypeTag> vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); VtkOutputFields::init(vtkWriter); //! Add model specific output fields - vtkWriter.addField(problem->getAnalyticalPressureSolution(), "pressureExact", 1); - vtkWriter.addField(problem->getAnalyticalVelocitySolution(), "velocityExact", GridView::dimensionworld); + vtkWriter.addField(problem->getAnalyticalPressureSolution(), "pressureExact"); + vtkWriter.addField(problem->getAnalyticalVelocitySolution(), "velocityExact"); vtkWriter.addFaceField(problem->getAnalyticalVelocitySolutionOnFace(), "faceVelocityExact"); vtkWriter.write(0.0);