24#ifndef VTK_OUTPUT_MODULE_HH
25#define VTK_OUTPUT_MODULE_HH
29#include <dune/common/timer.hh>
30#include <dune/common/fvector.hh>
31#include <dune/common/typetraits.hh>
33#include <dune/geometry/type.hh>
34#include <dune/geometry/multilineargeometry.hh>
36#include <dune/grid/common/mcmgmapper.hh>
37#include <dune/grid/common/partitionset.hh>
38#include <dune/grid/io/file/vtk/vtkwriter.hh>
39#include <dune/grid/io/file/vtk/vtksequencewriter.hh>
40#include <dune/grid/common/partitionset.hh>
64template<
class Gr
idVariables,
class SolutionVector>
67 using GridGeometry =
typename GridVariables::GridGeometry;
69 using VV =
typename GridVariables::VolumeVariables;
70 using Scalar =
typename GridVariables::Scalar;
72 using GridView =
typename GridGeometry::GridView;
75 dim = GridView::dimension,
76 dimWorld = GridView::dimensionworld
79 using Element =
typename GridView::template Codim<0>::Entity;
80 using VolVarsVector = Dune::FieldVector<Scalar, dimWorld>;
83 static constexpr int dofCodim = isBox ? dim : 0;
85 struct VolVarScalarDataInfo { std::function<Scalar(
const VV&)> get; std::string
name; };
86 struct VolVarVectorDataInfo { std::function<VolVarsVector(
const VV&)> get; std::string
name; };
87 using Field = Vtk::template Field<GridView>;
102 const SolutionVector&
sol,
103 const std::string&
name,
105 Dune::VTK::DataMode dm = Dune::VTK::conforming,
114 , sequenceWriter_(writer_,
name)
120 {
return paramGroup_; }
141 volVarScalarDataInfo_.push_back(VolVarScalarDataInfo{f,
name});
148 template<
class VVV = VolVarsVector,
typename std::enable_if_t<(VVV::dimension > 1),
int> = 0>
151 volVarVectorDataInfo_.push_back(VolVarVectorDataInfo{f,
name});
160 template<
typename Vector>
164 const auto nComp = getNumberOfComponents_(v);
166 const auto numElemDofs =
gridGeometry().elementMapper().size();
167 const auto numVertexDofs =
gridGeometry().vertexMapper().size();
172 if(numElemDofs == numVertexDofs)
173 DUNE_THROW(Dune::InvalidStateException,
"Automatic deduction of FieldType failed. Please explicitly specify FieldType::element or FieldType::vertex.");
175 if(v.size() == numElemDofs)
177 else if(v.size() == numVertexDofs)
180 DUNE_THROW(Dune::RangeError,
"Size mismatch of added field!");
186 if(v.size() != numElemDofs)
187 DUNE_THROW(Dune::RangeError,
"Size mismatch of added field!");
190 if(v.size() != numVertexDofs)
191 DUNE_THROW(Dune::RangeError,
"Size mismatch of added field!");
210 void write(
double time, Dune::VTK::OutputType type = Dune::VTK::ascii)
215 if (dm_ == Dune::VTK::conforming)
216 writeConforming_(time, type);
217 else if (dm_ == Dune::VTK::nonconforming)
218 writeNonConforming_(time, type);
220 DUNE_THROW(Dune::NotImplemented,
"Output for provided vtk data mode");
226 std::cout <<
"Writing output for problem \"" << name_ <<
"\". Took " << timer.elapsed() <<
" seconds." << std::endl;
232 const auto&
problem()
const {
return gridVariables_.curGridVolVars().problem(); }
233 const GridGeometry&
gridGeometry()
const {
return gridVariables_.gridGeometry(); }
235 const SolutionVector&
sol()
const {
return sol_; }
238 const std::string&
name()
const {
return name_; }
239 Dune::VTK::DataMode
dataMode()
const {
return dm_; }
241 Dune::VTKWriter<GridView>&
writer() {
return *writer_; }
246 const std::vector<Field>&
fields()
const {
return fields_; }
254 void writeConforming_(
double time, Dune::VTK::OutputType type)
262 std::vector<VelocityVector> velocity(velocityOutput_->numFluidPhases());
265 static bool addProcessRank = getParamFromGroup<bool>(paramGroup_,
"Vtk.AddProcessRank");
266 std::vector<double> rank;
269 std::vector<std::vector<Scalar>> volVarScalarData;
270 std::vector<std::vector<VolVarsVector>> volVarVectorData;
273 if (!volVarScalarDataInfo_.empty()
274 || !volVarVectorDataInfo_.empty()
276 || velocityOutput_->enableOutput()
279 const auto numCells =
gridGeometry().gridView().size(0);
280 const auto numDofs = numDofs_();
283 if (!volVarScalarDataInfo_.empty())
284 volVarScalarData.resize(volVarScalarDataInfo_.size(), std::vector<Scalar>(numDofs));
285 if (!volVarVectorDataInfo_.empty())
286 volVarVectorData.resize(volVarVectorDataInfo_.size(), std::vector<VolVarsVector>(numDofs));
288 if (velocityOutput_->enableOutput())
290 for (
int phaseIdx = 0; phaseIdx < velocityOutput_->numFluidPhases(); ++phaseIdx)
292 if(isBox && dim == 1)
293 velocity[phaseIdx].resize(numCells);
295 velocity[phaseIdx].resize(numDofs);
300 if (addProcessRank) rank.resize(numCells);
302 for (
const auto& element : elements(
gridGeometry().gridView(), Dune::Partitions::interior))
304 const auto eIdxGlobal =
gridGeometry().elementMapper().index(element);
307 auto elemVolVars =
localView(gridVariables_.curGridVolVars());
311 if (velocityOutput_->enableOutput())
313 fvGeometry.bind(element);
314 elemVolVars.bind(element, fvGeometry, sol_);
318 fvGeometry.bindElement(element);
319 elemVolVars.bindElement(element, fvGeometry, sol_);
322 if (!volVarScalarDataInfo_.empty()
323 || !volVarVectorDataInfo_.empty())
325 for (
auto&& scv : scvs(fvGeometry))
327 const auto dofIdxGlobal = scv.dofIndex();
328 const auto& volVars = elemVolVars[scv];
331 for (std::size_t i = 0; i < volVarScalarDataInfo_.size(); ++i)
332 volVarScalarData[i][dofIdxGlobal] = volVarScalarDataInfo_[i].get(volVars);
335 for (std::size_t i = 0; i < volVarVectorDataInfo_.size(); ++i)
336 volVarVectorData[i][dofIdxGlobal] = volVarVectorDataInfo_[i].get(volVars);
341 if (velocityOutput_->enableOutput())
343 auto elemFluxVarsCache =
localView(gridVariables_.gridFluxVarsCache());
344 elemFluxVarsCache.bind(element, fvGeometry, elemVolVars);
346 for (
int phaseIdx = 0; phaseIdx < velocityOutput_->numFluidPhases(); ++phaseIdx)
347 velocityOutput_->calculateVelocity(velocity[phaseIdx], element, fvGeometry, elemVolVars, elemFluxVarsCache, phaseIdx);
352 rank[eIdxGlobal] =
static_cast<double>(
gridGeometry().gridView().comm().rank());
362 for (std::size_t i = 0; i < volVarScalarDataInfo_.size(); ++i)
364 volVarScalarDataInfo_[i].
name, 1, dim).get() );
365 for (std::size_t i = 0; i < volVarVectorDataInfo_.size(); ++i)
367 volVarVectorDataInfo_[i].
name, dimWorld, dim).get() );
371 for (std::size_t i = 0; i < volVarScalarDataInfo_.size(); ++i)
373 volVarScalarDataInfo_[i].
name, 1, 0).get() );
374 for (std::size_t i = 0; i < volVarVectorDataInfo_.size(); ++i)
376 volVarVectorDataInfo_[i].
name, dimWorld, 0).get() );
380 if (velocityOutput_->enableOutput())
382 if (isBox && dim > 1)
384 for (
int phaseIdx = 0; phaseIdx < velocityOutput_->numFluidPhases(); ++phaseIdx)
386 "velocity_" + velocityOutput_->phaseName(phaseIdx) +
" (m/s)",
387 dimWorld, dim).get() );
392 for (
int phaseIdx = 0; phaseIdx < velocityOutput_->numFluidPhases(); ++phaseIdx)
394 "velocity_" + velocityOutput_->phaseName(phaseIdx) +
" (m/s)",
395 dimWorld, 0).get() );
401 sequenceWriter_.addCellData(Field(
gridGeometry().gridView(),
gridGeometry().elementMapper(), rank,
"process rank", 1, 0).get());
404 for (
auto&& field : fields_)
406 if (field.codim() == 0)
407 sequenceWriter_.addCellData(field.get());
408 else if (field.codim() == dim)
409 sequenceWriter_.addVertexData(field.get());
411 DUNE_THROW(Dune::RangeError,
"Cannot add wrongly sized vtk scalar field!");
418 sequenceWriter_.write(time, type);
427 void writeNonConforming_(
double time, Dune::VTK::OutputType type)
430 DUNE_THROW(Dune::InvalidStateException,
"Non-conforming output makes no sense for cell-centered schemes!");
437 bool enableVelocityOutput = getParamFromGroup<bool>(paramGroup_,
"Vtk.AddVelocity");
438 if (enableVelocityOutput ==
true && !velocityOutput_->enableOutput())
439 std::cerr <<
"Warning! Velocity output was enabled in the input file"
440 <<
" but no velocity output policy was set for the VTK output module:"
441 <<
" There will be no velocity output."
442 <<
" Use the addVelocityOutput member function of the VTK output module." << std::endl;
444 std::vector<VelocityVector> velocity(velocityOutput_->numFluidPhases());
447 static bool addProcessRank = getParamFromGroup<bool>(paramGroup_,
"Vtk.AddProcessRank");
448 std::vector<double> rank;
451 using ScalarDataContainer = std::vector< std::vector<Scalar> >;
452 using VectorDataContainer = std::vector< std::vector<VolVarsVector> >;
453 std::vector< ScalarDataContainer > volVarScalarData;
454 std::vector< VectorDataContainer > volVarVectorData;
457 if (!volVarScalarDataInfo_.empty()
458 || !volVarVectorDataInfo_.empty()
460 || velocityOutput_->enableOutput()
463 const auto numCells =
gridGeometry().gridView().size(0);
464 const auto numDofs = numDofs_();
467 if (!volVarScalarDataInfo_.empty())
468 volVarScalarData.resize(volVarScalarDataInfo_.size(), ScalarDataContainer(numCells));
469 if (!volVarVectorDataInfo_.empty())
470 volVarVectorData.resize(volVarVectorDataInfo_.size(), VectorDataContainer(numCells));
472 if (velocityOutput_->enableOutput())
474 for (
int phaseIdx = 0; phaseIdx < velocityOutput_->numFluidPhases(); ++phaseIdx)
476 if(isBox && dim == 1)
477 velocity[phaseIdx].resize(numCells);
479 velocity[phaseIdx].resize(numDofs);
484 if (addProcessRank) rank.resize(numCells);
486 for (
const auto& element : elements(
gridGeometry().gridView(), Dune::Partitions::interior))
488 const auto eIdxGlobal =
gridGeometry().elementMapper().index(element);
489 const auto numCorners = element.subEntities(dim);
492 auto elemVolVars =
localView(gridVariables_.curGridVolVars());
495 for (std::size_t i = 0; i < volVarScalarDataInfo_.size(); ++i)
496 volVarScalarData[i][eIdxGlobal].
resize(numCorners);
497 for (std::size_t i = 0; i < volVarVectorDataInfo_.size(); ++i)
498 volVarVectorData[i][eIdxGlobal].
resize(numCorners);
502 if (velocityOutput_->enableOutput())
504 fvGeometry.bind(element);
505 elemVolVars.bind(element, fvGeometry, sol_);
509 fvGeometry.bindElement(element);
510 elemVolVars.bindElement(element, fvGeometry, sol_);
513 if (!volVarScalarDataInfo_.empty()
514 || !volVarVectorDataInfo_.empty())
516 for (
auto&& scv : scvs(fvGeometry))
518 const auto& volVars = elemVolVars[scv];
521 for (std::size_t i = 0; i < volVarScalarDataInfo_.size(); ++i)
522 volVarScalarData[i][scv.elementIndex()][scv.localDofIndex()] = volVarScalarDataInfo_[i].get(volVars);
525 for (std::size_t i = 0; i < volVarVectorDataInfo_.size(); ++i)
526 volVarVectorData[i][scv.elementIndex()][scv.localDofIndex()] = volVarVectorDataInfo_[i].get(volVars);
531 if (velocityOutput_->enableOutput())
533 auto elemFluxVarsCache =
localView(gridVariables_.gridFluxVarsCache());
534 elemFluxVarsCache.bind(element, fvGeometry, elemVolVars);
536 for (
int phaseIdx = 0; phaseIdx < velocityOutput_->numFluidPhases(); ++phaseIdx)
537 velocityOutput_->calculateVelocity(velocity[phaseIdx], element, fvGeometry, elemVolVars, elemFluxVarsCache, phaseIdx);
542 rank[eIdxGlobal] =
static_cast<double>(
gridGeometry().gridView().comm().rank());
550 for (std::size_t i = 0; i < volVarScalarDataInfo_.size(); ++i)
551 sequenceWriter_.addVertexData( Field(
gridGeometry().gridView(),
gridGeometry().elementMapper(), volVarScalarData[i],
552 volVarScalarDataInfo_[i].
name, 1, dim, dm_).get() );
554 for (std::size_t i = 0; i < volVarVectorDataInfo_.size(); ++i)
555 sequenceWriter_.addVertexData( Field(
gridGeometry().gridView(),
gridGeometry().elementMapper(), volVarVectorData[i],
556 volVarVectorDataInfo_[i].
name, dimWorld, dim, dm_).get() );
559 if (velocityOutput_->enableOutput())
563 for (
int phaseIdx = 0; phaseIdx < velocityOutput_->numFluidPhases(); ++phaseIdx)
565 "velocity_" + velocityOutput_->phaseName(phaseIdx) +
" (m/s)",
566 dimWorld, dim).get() );
570 for (
int phaseIdx = 0; phaseIdx < velocityOutput_->numFluidPhases(); ++phaseIdx)
572 "velocity_" + velocityOutput_->phaseName(phaseIdx) +
" (m/s)",
573 dimWorld, 0).get() );
578 sequenceWriter_.addCellData( Field(
gridGeometry().gridView(),
gridGeometry().elementMapper(), rank,
"process rank", 1, 0).get() );
581 for (
auto&& field : fields_)
583 if (field.codim() == 0)
584 sequenceWriter_.addCellData(field.get());
585 else if (field.codim() == dim)
586 sequenceWriter_.addVertexData(field.get());
588 DUNE_THROW(Dune::RangeError,
"Cannot add wrongly sized vtk scalar field!");
595 sequenceWriter_.write(time, type);
604 template<class Vector, typename std::enable_if_t<IsIndexable<decltype(std::declval<Vector>()[0])>::value,
int> = 0>
605 std::size_t getNumberOfComponents_(
const Vector& v) {
return v[0].size(); }
608 template<class Vector, typename std::enable_if_t<!IsIndexable<decltype(std::declval<Vector>()[0])>::value,
int> = 0>
609 std::size_t getNumberOfComponents_(
const Vector& v) {
return 1; }
612 std::size_t numDofs_()
const {
return dofCodim == dim ?
gridGeometry().vertexMapper().size() :
gridGeometry().elementMapper().size(); }
614 const GridVariables& gridVariables_;
615 const SolutionVector& sol_;
618 std::string paramGroup_;
620 Dune::VTK::DataMode dm_;
622 std::shared_ptr<Dune::VTKWriter<GridView>> writer_;
623 Dune::VTKSequenceWriter<GridView> sequenceWriter_;
625 std::vector<VolVarScalarDataInfo> volVarScalarDataInfo_;
626 std::vector<VolVarVectorDataInfo> volVarVectorDataInfo_;
628 std::vector<Field> fields_;
629 std::shared_ptr<VelocityOutput> velocityOutput_;
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
The available discretization methods in Dumux.
Dune style VTK functions.
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition: localview.hh:38
make the local view function available whenever we use the grid geometry
Definition: adapt.hh:29
Definition: common/properties/model.hh:34
void resize(const Vector &v, std::size_t size)
Definition: test_isvalid.cc:26
Velocity output for implicit (porous media) models.
Definition: io/velocityoutput.hh:41
std::vector< Dune::FieldVector< Scalar, dimWorld > > VelocityVector
Definition: io/velocityoutput.hh:50
A VTK output module to simplify writing dumux simulation data to VTK format.
Definition: io/vtkoutputmodule.hh:66
const auto & problem() const
Definition: io/vtkoutputmodule.hh:232
const GridVariables & gridVariables() const
Definition: io/vtkoutputmodule.hh:234
void addVolumeVariable(std::function< VolVarsVector(const VolumeVariables &)> &&f, const std::string &name)
Definition: io/vtkoutputmodule.hh:149
VV VolumeVariables
export type of the volume variables for the outputfields
Definition: io/vtkoutputmodule.hh:93
void write(double time, Dune::VTK::OutputType type=Dune::VTK::ascii)
Writing data.
Definition: io/vtkoutputmodule.hh:210
const std::string & paramGroup() const
the parameter group for getting parameter from the parameter tree
Definition: io/vtkoutputmodule.hh:119
void addVolumeVariable(std::function< Scalar(const VolumeVariables &)> &&f, const std::string &name)
Definition: io/vtkoutputmodule.hh:139
bool verbose() const
Definition: io/vtkoutputmodule.hh:237
Dune::VTKSequenceWriter< GridView > & sequenceWriter()
Definition: io/vtkoutputmodule.hh:242
void addVelocityOutput(std::shared_ptr< VelocityOutputType > velocityOutput)
Add a velocity output policy.
Definition: io/vtkoutputmodule.hh:133
const VelocityOutput & velocityOutput() const
Definition: io/vtkoutputmodule.hh:249
void addField(const Vector &v, const std::string &name, FieldType fieldType=FieldType::automatic)
Definition: io/vtkoutputmodule.hh:161
const std::string & name() const
Definition: io/vtkoutputmodule.hh:238
Dune::VTK::DataMode dataMode() const
Definition: io/vtkoutputmodule.hh:239
Dune::VTKWriter< GridView > & writer()
Definition: io/vtkoutputmodule.hh:241
FieldType
export field type
Definition: io/vtkoutputmodule.hh:97
const SolutionVector & sol() const
Definition: io/vtkoutputmodule.hh:235
const GridGeometry & gridGeometry() const
Definition: io/vtkoutputmodule.hh:233
const std::vector< Field > & fields() const
Definition: io/vtkoutputmodule.hh:246
VtkOutputModule(const GridVariables &gridVariables, const SolutionVector &sol, const std::string &name, const std::string ¶mGroup="", Dune::VTK::DataMode dm=Dune::VTK::conforming, bool verbose=true)
Definition: io/vtkoutputmodule.hh:101
const std::vector< VolVarScalarDataInfo > & volVarScalarDataInfo() const
Definition: io/vtkoutputmodule.hh:244
const std::vector< VolVarVectorDataInfo > & volVarVectorDataInfo() const
Definition: io/vtkoutputmodule.hh:245
Velocity output for porous media models.