3.3.0
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
io/vtkoutputmodule.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3/*****************************************************************************
4 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
24#ifndef DUMUX_IO_VTK_OUTPUT_MODULE_HH
25#define DUMUX_IO_VTK_OUTPUT_MODULE_HH
26
27#include <functional>
28#include <memory>
29#include <string>
30
31#include <dune/common/timer.hh>
32#include <dune/common/fvector.hh>
33#include <dune/common/typetraits.hh>
34
35#include <dune/geometry/type.hh>
36#include <dune/geometry/multilineargeometry.hh>
37
38#include <dune/grid/common/mcmgmapper.hh>
39#include <dune/grid/common/partitionset.hh>
40#include <dune/grid/io/file/vtk/vtkwriter.hh>
41#include <dune/grid/io/file/vtk/vtksequencewriter.hh>
42#include <dune/grid/common/partitionset.hh>
43
46#include <dumux/io/format.hh>
48
49#include "vtkfunction.hh"
50#include "velocityoutput.hh"
51
52namespace Dumux {
53
59template<class GridGeometry>
61{
62 using GridView = typename GridGeometry::GridView;
63 using Field = Vtk::template Field<GridView>;
64 static constexpr int dim = GridView::dimension;
65
66public:
68 enum class FieldType : unsigned int
69 {
70 element, vertex, automatic
71 };
72
73 VtkOutputModuleBase(const GridGeometry& gridGeometry,
74 const std::string& name,
75 const std::string& paramGroup = "",
76 Dune::VTK::DataMode dm = Dune::VTK::conforming,
77 bool verbose = true)
78 : gridGeometry_(gridGeometry)
79 , name_(name)
80 , paramGroup_(paramGroup)
81 , dm_(dm)
82 , verbose_(gridGeometry.gridView().comm().rank() == 0 && verbose)
83 {
84 const auto precisionString = getParamFromGroup<std::string>(paramGroup, "Vtk.Precision", "Float32");
85 precision_ = Dumux::Vtk::stringToPrecision(precisionString);
86 const auto coordPrecision = Dumux::Vtk::stringToPrecision(getParamFromGroup<std::string>(paramGroup, "Vtk.CoordPrecision", precisionString));
87 writer_ = std::make_shared<Dune::VTKWriter<GridView>>(gridGeometry.gridView(), dm, coordPrecision);
88 sequenceWriter_ = std::make_unique<Dune::VTKSequenceWriter<GridView>>(writer_, name);
89 }
90
91 virtual ~VtkOutputModuleBase() = default;
92
94 const std::string& paramGroup() const
95 { return paramGroup_; }
96
106 template<typename Vector>
107 void addField(const Vector& v,
108 const std::string& name,
110 { addField(v, name, this->precision(), fieldType); }
111
122 template<typename Vector>
123 void addField(const Vector& v,
124 const std::string& name,
125 Dumux::Vtk::Precision precision,
127 {
128 // Deduce the number of components from the given vector type
129 const auto nComp = getNumberOfComponents_(v);
130
131 const auto numElemDofs = gridGeometry().elementMapper().size();
132 const auto numVertexDofs = gridGeometry().vertexMapper().size();
133
134 // Automatically deduce the field type ...
135 if(fieldType == FieldType::automatic)
136 {
137 if(numElemDofs == numVertexDofs)
138 DUNE_THROW(Dune::InvalidStateException, "Automatic deduction of FieldType failed. Please explicitly specify FieldType::element or FieldType::vertex.");
139
140 if(v.size() == numElemDofs)
141 fieldType = FieldType::element;
142 else if(v.size() == numVertexDofs)
143 fieldType = FieldType::vertex;
144 else
145 DUNE_THROW(Dune::RangeError, "Size mismatch of added field!");
146 }
147 // ... or check if the user-specified type matches the size of v
148 else
149 {
150 if(fieldType == FieldType::element)
151 if(v.size() != numElemDofs)
152 DUNE_THROW(Dune::RangeError, "Size mismatch of added field!");
153
154 if(fieldType == FieldType::vertex)
155 if(v.size() != numVertexDofs)
156 DUNE_THROW(Dune::RangeError, "Size mismatch of added field!");
157 }
158
159 // add the appropriate field
160 if (fieldType == FieldType::element)
161 fields_.emplace_back(gridGeometry_.gridView(), gridGeometry_.elementMapper(), v, name, nComp, 0, dm_, precision);
162 else
163 fields_.emplace_back(gridGeometry_.gridView(), gridGeometry_.vertexMapper(), v, name, nComp, dim, dm_, precision);
164 }
165
171 void write(double time, Dune::VTK::OutputType type = Dune::VTK::ascii)
172 {
173 Dune::Timer timer;
174
175 // write to file depending on data mode
176 if (dm_ == Dune::VTK::conforming)
177 writeConforming_(time, type);
178 else if (dm_ == Dune::VTK::nonconforming)
179 writeNonConforming_(time, type);
180 else
181 DUNE_THROW(Dune::NotImplemented, "Output for provided VTK data mode");
182
184 timer.stop();
185 if (verbose_)
186 std::cout << Fmt::format("Writing output for problem \"{}\". Took {:.2g} seconds.\n", name_, timer.elapsed());
187 }
188
189protected:
190 const GridGeometry& gridGeometry() const { return gridGeometry_; }
191
192 bool verbose() const { return verbose_; }
193 const std::string& name() const { return name_; }
194 Dune::VTK::DataMode dataMode() const { return dm_; }
195 Dumux::Vtk::Precision precision() const { return precision_; }
196
197 Dune::VTKWriter<GridView>& writer() { return *writer_; }
198 Dune::VTKSequenceWriter<GridView>& sequenceWriter() { return *sequenceWriter_; }
199
200 const std::vector<Field>& fields() const { return fields_; }
201
202private:
204 virtual void writeConforming_(double time, Dune::VTK::OutputType type)
205 {
209
210 // process rank
211 static bool addProcessRank = getParamFromGroup<bool>(this->paramGroup(), "Vtk.AddProcessRank");
212 std::vector<int> rank;
213
215 if (!fields_.empty() || addProcessRank)
216 {
217 const auto numCells = gridGeometry_.gridView().size(0);
218
219 // maybe allocate space for the process rank
220 if (addProcessRank)
221 {
222 rank.resize(numCells);
223
224 for (const auto& element : elements(gridGeometry_.gridView(), Dune::Partitions::interior))
225 {
226 const auto eIdxGlobal = gridGeometry_.elementMapper().index(element);
227 rank[eIdxGlobal] = gridGeometry_.gridView().comm().rank();
228 }
229 }
230
234
235 // the process rank
236 if (addProcessRank)
237 this->sequenceWriter().addCellData(Field(gridGeometry_.gridView(), gridGeometry_.elementMapper(), rank, "process rank", 1, 0).get());
238
239 // also register additional (non-standardized) user fields if any
240 for (auto&& field : fields_)
241 {
242 if (field.codim() == 0)
243 this->sequenceWriter().addCellData(field.get());
244 else if (field.codim() == dim)
245 this->sequenceWriter().addVertexData(field.get());
246 else
247 DUNE_THROW(Dune::RangeError, "Cannot add wrongly sized vtk scalar field!");
248 }
249 }
250
254 this->sequenceWriter().write(time, type);
255
259 this->writer().clear();
260 }
261
263 virtual void writeNonConforming_(double time, Dune::VTK::OutputType type)
264 {
265 DUNE_THROW(Dune::NotImplemented, "Non-conforming VTK output");
266 }
267
269 template<class Vector>
270 std::size_t getNumberOfComponents_(const Vector& v)
271 {
272 if constexpr (IsIndexable<decltype(std::declval<Vector>()[0])>::value)
273 return v[0].size();
274 else
275 return 1;
276 }
277
278 const GridGeometry& gridGeometry_;
279 std::string name_;
280 const std::string paramGroup_;
281 Dune::VTK::DataMode dm_;
282 bool verbose_;
283 Dumux::Vtk::Precision precision_;
284
285 std::shared_ptr<Dune::VTKWriter<GridView>> writer_;
286 std::unique_ptr<Dune::VTKSequenceWriter<GridView>> sequenceWriter_;
287
288 std::vector<Field> fields_;
289};
290
303template<class GridVariables, class SolutionVector>
304class VtkOutputModule : public VtkOutputModuleBase<typename GridVariables::GridGeometry>
305{
307 using GridGeometry = typename GridVariables::GridGeometry;
308
309 using VV = typename GridVariables::VolumeVariables;
310 using Scalar = typename GridVariables::Scalar;
311
312 using GridView = typename GridGeometry::GridView;
313
314 enum {
315 dim = GridView::dimension,
316 dimWorld = GridView::dimensionworld
317 };
318
319 using Element = typename GridView::template Codim<0>::Entity;
320 using VolVarsVector = Dune::FieldVector<Scalar, dimWorld>;
321
322 static constexpr bool isBox = GridGeometry::discMethod == DiscretizationMethod::box;
323 static constexpr int dofCodim = isBox ? dim : 0;
324
325 struct VolVarScalarDataInfo { std::function<Scalar(const VV&)> get; std::string name; Dumux::Vtk::Precision precision_; };
326 struct VolVarVectorDataInfo { std::function<VolVarsVector(const VV&)> get; std::string name; Dumux::Vtk::Precision precision_; };
327 using Field = Vtk::template Field<GridView>;
328
330
331public:
333 using VolumeVariables = VV;
334
335 VtkOutputModule(const GridVariables& gridVariables,
336 const SolutionVector& sol,
337 const std::string& name,
338 const std::string& paramGroup = "",
339 Dune::VTK::DataMode dm = Dune::VTK::conforming,
340 bool verbose = true)
342 , gridVariables_(gridVariables)
343 , sol_(sol)
344 , velocityOutput_(std::make_shared<VelocityOutputType>())
345 {}
346
351
358 void addVelocityOutput(std::shared_ptr<VelocityOutputType> velocityOutput)
359 { velocityOutput_ = velocityOutput; }
360
364 void addVolumeVariable(std::function<Scalar(const VolumeVariables&)>&& f,
365 const std::string& name)
366 {
367 volVarScalarDataInfo_.push_back(VolVarScalarDataInfo{f, name, this->precision()});
368 }
369
374 template<class VVV = VolVarsVector, typename std::enable_if_t<(VVV::dimension > 1), int> = 0>
375 void addVolumeVariable(std::function<VolVarsVector(const VolumeVariables&)>&& f,
376 const std::string& name)
377 {
378 volVarVectorDataInfo_.push_back(VolVarVectorDataInfo{f, name, this->precision()});
379 }
380
381protected:
382 // some return functions for differing implementations to use
383 const auto& problem() const { return gridVariables_.curGridVolVars().problem(); }
384 const GridVariables& gridVariables() const { return gridVariables_; }
385 const GridGeometry& gridGeometry() const { return gridVariables_.gridGeometry(); }
386 const SolutionVector& sol() const { return sol_; }
387
388 const std::vector<VolVarScalarDataInfo>& volVarScalarDataInfo() const { return volVarScalarDataInfo_; }
389 const std::vector<VolVarVectorDataInfo>& volVarVectorDataInfo() const { return volVarVectorDataInfo_; }
390
392 const VelocityOutput& velocityOutput() const { return *velocityOutput_; }
393
394private:
395
397 void writeConforming_(double time, Dune::VTK::OutputType type) override
398 {
399 const Dune::VTK::DataMode dm = Dune::VTK::conforming;
403
404 // instantiate the velocity output
405 using VelocityVector = typename VelocityOutput::VelocityVector;
406 std::vector<VelocityVector> velocity(velocityOutput_->numFluidPhases());
407
408 // process rank
409 static bool addProcessRank = getParamFromGroup<bool>(this->paramGroup(), "Vtk.AddProcessRank");
410 std::vector<double> rank;
411
412 // volume variable data
413 std::vector<std::vector<Scalar>> volVarScalarData;
414 std::vector<std::vector<VolVarsVector>> volVarVectorData;
415
417 if (!volVarScalarDataInfo_.empty()
418 || !volVarVectorDataInfo_.empty()
419 || !this->fields().empty()
420 || velocityOutput_->enableOutput()
421 || addProcessRank)
422 {
423 const auto numCells = gridGeometry().gridView().size(0);
424 const auto numDofs = numDofs_();
425
426 // get fields for all volume variables
427 if (!volVarScalarDataInfo_.empty())
428 volVarScalarData.resize(volVarScalarDataInfo_.size(), std::vector<Scalar>(numDofs));
429 if (!volVarVectorDataInfo_.empty())
430 volVarVectorData.resize(volVarVectorDataInfo_.size(), std::vector<VolVarsVector>(numDofs));
431
432 if (velocityOutput_->enableOutput())
433 {
434 for (int phaseIdx = 0; phaseIdx < velocityOutput_->numFluidPhases(); ++phaseIdx)
435 {
436 if(isBox && dim == 1)
437 velocity[phaseIdx].resize(numCells);
438 else
439 velocity[phaseIdx].resize(numDofs);
440 }
441 }
442
443 // maybe allocate space for the process rank
444 if (addProcessRank) rank.resize(numCells);
445
446 for (const auto& element : elements(gridGeometry().gridView(), Dune::Partitions::interior))
447 {
448 const auto eIdxGlobal = gridGeometry().elementMapper().index(element);
449
450 auto fvGeometry = localView(gridGeometry());
451 auto elemVolVars = localView(gridVariables_.curGridVolVars());
452
453 // If velocity output is enabled we need to bind to the whole stencil
454 // otherwise element-local data is sufficient
455 if (velocityOutput_->enableOutput())
456 {
457 fvGeometry.bind(element);
458 elemVolVars.bind(element, fvGeometry, sol_);
459 }
460 else
461 {
462 fvGeometry.bindElement(element);
463 elemVolVars.bindElement(element, fvGeometry, sol_);
464 }
465
466 if (!volVarScalarDataInfo_.empty()
467 || !volVarVectorDataInfo_.empty())
468 {
469 for (auto&& scv : scvs(fvGeometry))
470 {
471 const auto dofIdxGlobal = scv.dofIndex();
472 const auto& volVars = elemVolVars[scv];
473
474 // get the scalar-valued data
475 for (std::size_t i = 0; i < volVarScalarDataInfo_.size(); ++i)
476 volVarScalarData[i][dofIdxGlobal] = volVarScalarDataInfo_[i].get(volVars);
477
478 // get the vector-valued data
479 for (std::size_t i = 0; i < volVarVectorDataInfo_.size(); ++i)
480 volVarVectorData[i][dofIdxGlobal] = volVarVectorDataInfo_[i].get(volVars);
481 }
482 }
483
484 // velocity output
485 if (velocityOutput_->enableOutput())
486 {
487 auto elemFluxVarsCache = localView(gridVariables_.gridFluxVarsCache());
488 elemFluxVarsCache.bind(element, fvGeometry, elemVolVars);
489
490 for (int phaseIdx = 0; phaseIdx < velocityOutput_->numFluidPhases(); ++phaseIdx)
491 velocityOutput_->calculateVelocity(velocity[phaseIdx], element, fvGeometry, elemVolVars, elemFluxVarsCache, phaseIdx);
492 }
493
495 if (addProcessRank)
496 rank[eIdxGlobal] = static_cast<double>(gridGeometry().gridView().comm().rank());
497 }
498
502
503 // volume variables if any
504 if (isBox)
505 {
506 for (std::size_t i = 0; i < volVarScalarDataInfo_.size(); ++i)
507 this->sequenceWriter().addVertexData( Field(gridGeometry().gridView(), gridGeometry().vertexMapper(), volVarScalarData[i],
508 volVarScalarDataInfo_[i].name, /*numComp*/1, /*codim*/dim, dm, this->precision()).get() );
509 for (std::size_t i = 0; i < volVarVectorDataInfo_.size(); ++i)
510 this->sequenceWriter().addVertexData( Field(gridGeometry().gridView(), gridGeometry().vertexMapper(), volVarVectorData[i],
511 volVarVectorDataInfo_[i].name, /*numComp*/dimWorld, /*codim*/dim, dm, this->precision()).get() );
512 }
513 else
514 {
515 for (std::size_t i = 0; i < volVarScalarDataInfo_.size(); ++i)
516 this->sequenceWriter().addCellData( Field(gridGeometry().gridView(), gridGeometry().elementMapper(), volVarScalarData[i],
517 volVarScalarDataInfo_[i].name, /*numComp*/1, /*codim*/0,dm, this->precision()).get() );
518 for (std::size_t i = 0; i < volVarVectorDataInfo_.size(); ++i)
519 this->sequenceWriter().addCellData( Field(gridGeometry().gridView(), gridGeometry().elementMapper(), volVarVectorData[i],
520 volVarVectorDataInfo_[i].name, /*numComp*/dimWorld, /*codim*/0,dm, this->precision()).get() );
521 }
522
523 // the velocity field
524 if (velocityOutput_->enableOutput())
525 {
526 if (isBox && dim > 1)
527 {
528 for (int phaseIdx = 0; phaseIdx < velocityOutput_->numFluidPhases(); ++phaseIdx)
529 this->sequenceWriter().addVertexData( Field(gridGeometry().gridView(), gridGeometry().vertexMapper(), velocity[phaseIdx],
530 "velocity_" + velocityOutput_->phaseName(phaseIdx) + " (m/s)",
531 /*numComp*/dimWorld, /*codim*/dim, dm, this->precision()).get() );
532 }
533 // cell-centered models
534 else
535 {
536 for (int phaseIdx = 0; phaseIdx < velocityOutput_->numFluidPhases(); ++phaseIdx)
537 this->sequenceWriter().addCellData( Field(gridGeometry().gridView(), gridGeometry().elementMapper(), velocity[phaseIdx],
538 "velocity_" + velocityOutput_->phaseName(phaseIdx) + " (m/s)",
539 /*numComp*/dimWorld, /*codim*/0, dm, this->precision()).get() );
540 }
541 }
542
543 // the process rank
544 if (addProcessRank)
545 this->sequenceWriter().addCellData(Field(gridGeometry().gridView(), gridGeometry().elementMapper(), rank, "process rank", 1, 0).get());
546
547 // also register additional (non-standardized) user fields if any
548 for (auto&& field : this->fields())
549 {
550 if (field.codim() == 0)
551 this->sequenceWriter().addCellData(field.get());
552 else if (field.codim() == dim)
553 this->sequenceWriter().addVertexData(field.get());
554 else
555 DUNE_THROW(Dune::RangeError, "Cannot add wrongly sized vtk scalar field!");
556 }
557 }
558
562 this->sequenceWriter().write(time, type);
563
567 this->writer().clear();
568 }
569
571 void writeNonConforming_(double time, Dune::VTK::OutputType type) override
572 {
573 const Dune::VTK::DataMode dm = Dune::VTK::nonconforming;
574
575 if(!isBox)
576 DUNE_THROW(Dune::InvalidStateException, "Non-conforming output makes no sense for cell-centered schemes!");
577
581
582 // check the velocity output
583 bool enableVelocityOutput = getParamFromGroup<bool>(this->paramGroup(), "Vtk.AddVelocity");
584 if (enableVelocityOutput == true && !velocityOutput_->enableOutput())
585 std::cerr << "Warning! Velocity output was enabled in the input file"
586 << " but no velocity output policy was set for the VTK output module:"
587 << " There will be no velocity output."
588 << " Use the addVelocityOutput member function of the VTK output module." << std::endl;
589 using VelocityVector = typename VelocityOutput::VelocityVector;
590 std::vector<VelocityVector> velocity(velocityOutput_->numFluidPhases());
591
592 // process rank
593 static bool addProcessRank = getParamFromGroup<bool>(this->paramGroup(), "Vtk.AddProcessRank");
594 std::vector<double> rank;
595
596 // volume variable data (indexing: volvardata/element/localcorner)
597 using ScalarDataContainer = std::vector< std::vector<Scalar> >;
598 using VectorDataContainer = std::vector< std::vector<VolVarsVector> >;
599 std::vector< ScalarDataContainer > volVarScalarData;
600 std::vector< VectorDataContainer > volVarVectorData;
601
603 if (!volVarScalarDataInfo_.empty()
604 || !volVarVectorDataInfo_.empty()
605 || !this->fields().empty()
606 || velocityOutput_->enableOutput()
607 || addProcessRank)
608 {
609 const auto numCells = gridGeometry().gridView().size(0);
610 const auto numDofs = numDofs_();
611
612 // get fields for all volume variables
613 if (!volVarScalarDataInfo_.empty())
614 volVarScalarData.resize(volVarScalarDataInfo_.size(), ScalarDataContainer(numCells));
615 if (!volVarVectorDataInfo_.empty())
616 volVarVectorData.resize(volVarVectorDataInfo_.size(), VectorDataContainer(numCells));
617
618 if (velocityOutput_->enableOutput())
619 {
620 for (int phaseIdx = 0; phaseIdx < velocityOutput_->numFluidPhases(); ++phaseIdx)
621 {
622 if(isBox && dim == 1)
623 velocity[phaseIdx].resize(numCells);
624 else
625 velocity[phaseIdx].resize(numDofs);
626 }
627 }
628
629 // maybe allocate space for the process rank
630 if (addProcessRank) rank.resize(numCells);
631
632 for (const auto& element : elements(gridGeometry().gridView(), Dune::Partitions::interior))
633 {
634 const auto eIdxGlobal = gridGeometry().elementMapper().index(element);
635 const auto numCorners = element.subEntities(dim);
636
637 auto fvGeometry = localView(gridGeometry());
638 auto elemVolVars = localView(gridVariables_.curGridVolVars());
639
640 // resize element-local data containers
641 for (std::size_t i = 0; i < volVarScalarDataInfo_.size(); ++i)
642 volVarScalarData[i][eIdxGlobal].resize(numCorners);
643 for (std::size_t i = 0; i < volVarVectorDataInfo_.size(); ++i)
644 volVarVectorData[i][eIdxGlobal].resize(numCorners);
645
646 // If velocity output is enabled we need to bind to the whole stencil
647 // otherwise element-local data is sufficient
648 if (velocityOutput_->enableOutput())
649 {
650 fvGeometry.bind(element);
651 elemVolVars.bind(element, fvGeometry, sol_);
652 }
653 else
654 {
655 fvGeometry.bindElement(element);
656 elemVolVars.bindElement(element, fvGeometry, sol_);
657 }
658
659 if (!volVarScalarDataInfo_.empty()
660 || !volVarVectorDataInfo_.empty())
661 {
662 for (auto&& scv : scvs(fvGeometry))
663 {
664 const auto& volVars = elemVolVars[scv];
665
666 // get the scalar-valued data
667 for (std::size_t i = 0; i < volVarScalarDataInfo_.size(); ++i)
668 volVarScalarData[i][scv.elementIndex()][scv.localDofIndex()] = volVarScalarDataInfo_[i].get(volVars);
669
670 // get the vector-valued data
671 for (std::size_t i = 0; i < volVarVectorDataInfo_.size(); ++i)
672 volVarVectorData[i][scv.elementIndex()][scv.localDofIndex()] = volVarVectorDataInfo_[i].get(volVars);
673 }
674 }
675
676 // velocity output
677 if (velocityOutput_->enableOutput())
678 {
679 auto elemFluxVarsCache = localView(gridVariables_.gridFluxVarsCache());
680 elemFluxVarsCache.bind(element, fvGeometry, elemVolVars);
681
682 for (int phaseIdx = 0; phaseIdx < velocityOutput_->numFluidPhases(); ++phaseIdx)
683 velocityOutput_->calculateVelocity(velocity[phaseIdx], element, fvGeometry, elemVolVars, elemFluxVarsCache, phaseIdx);
684 }
685
687 if (addProcessRank)
688 rank[eIdxGlobal] = static_cast<double>(gridGeometry().gridView().comm().rank());
689 }
690
694
695 // volume variables if any
696 for (std::size_t i = 0; i < volVarScalarDataInfo_.size(); ++i)
697 this->sequenceWriter().addVertexData( Field(gridGeometry().gridView(), gridGeometry().elementMapper(), volVarScalarData[i],
698 volVarScalarDataInfo_[i].name, /*numComp*/1, /*codim*/dim, /*nonconforming*/dm, this->precision()).get() );
699
700 for (std::size_t i = 0; i < volVarVectorDataInfo_.size(); ++i)
701 this->sequenceWriter().addVertexData( Field(gridGeometry().gridView(), gridGeometry().elementMapper(), volVarVectorData[i],
702 volVarVectorDataInfo_[i].name, /*numComp*/dimWorld, /*codim*/dim, /*nonconforming*/dm, this->precision()).get() );
703
704 // the velocity field
705 if (velocityOutput_->enableOutput())
706 {
707 // node-wise velocities
708 if (dim > 1)
709 for (int phaseIdx = 0; phaseIdx < velocityOutput_->numFluidPhases(); ++phaseIdx)
710 this->sequenceWriter().addVertexData( Field(gridGeometry().gridView(), gridGeometry().vertexMapper(), velocity[phaseIdx],
711 "velocity_" + velocityOutput_->phaseName(phaseIdx) + " (m/s)",
712 /*numComp*/dimWorld, /*codim*/dim, dm, this->precision()).get() );
713
714 // cell-wise velocities
715 else
716 for (int phaseIdx = 0; phaseIdx < velocityOutput_->numFluidPhases(); ++phaseIdx)
717 this->sequenceWriter().addCellData( Field(gridGeometry().gridView(), gridGeometry().elementMapper(), velocity[phaseIdx],
718 "velocity_" + velocityOutput_->phaseName(phaseIdx) + " (m/s)",
719 /*numComp*/dimWorld, /*codim*/0,dm, this->precision()).get());
720 }
721
722 // the process rank
723 if (addProcessRank)
724 this->sequenceWriter().addCellData( Field(gridGeometry().gridView(), gridGeometry().elementMapper(), rank, "process rank", 1, 0).get() );
725
726 // also register additional (non-standardized) user fields if any
727 for (auto&& field : this->fields())
728 {
729 if (field.codim() == 0)
730 this->sequenceWriter().addCellData(field.get());
731 else if (field.codim() == dim)
732 this->sequenceWriter().addVertexData(field.get());
733 else
734 DUNE_THROW(Dune::RangeError, "Cannot add wrongly sized vtk scalar field!");
735 }
736 }
737
741 this->sequenceWriter().write(time, type);
742
746 this->writer().clear();
747 }
748
750 std::size_t numDofs_() const { return dofCodim == dim ? gridGeometry().vertexMapper().size() : gridGeometry().elementMapper().size(); }
751
752 const GridVariables& gridVariables_;
753 const SolutionVector& sol_;
754
755 std::vector<VolVarScalarDataInfo> volVarScalarDataInfo_;
756 std::vector<VolVarVectorDataInfo> volVarVectorDataInfo_;
757
758 std::shared_ptr<VelocityOutput> velocityOutput_;
759};
760
761} // end namespace Dumux
762
763#endif
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
The available discretization methods in Dumux.
Formatting based on the fmt-library which implements std::format of C++20.
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
Precision stringToPrecision(std::string_view precisionName)
Maps a string (e.g. from input) to a Dune precision type.
Definition: vtkprecision.hh:39
Definition: adapt.hh:29
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:61
Dumux::Vtk::Precision precision() const
Definition: io/vtkoutputmodule.hh:195
const std::string & paramGroup() const
the parameter group for getting parameter from the parameter tree
Definition: io/vtkoutputmodule.hh:94
void write(double time, Dune::VTK::OutputType type=Dune::VTK::ascii)
Definition: io/vtkoutputmodule.hh:171
VtkOutputModuleBase(const GridGeometry &gridGeometry, const std::string &name, const std::string &paramGroup="", Dune::VTK::DataMode dm=Dune::VTK::conforming, bool verbose=true)
Definition: io/vtkoutputmodule.hh:73
FieldType
export field type
Definition: io/vtkoutputmodule.hh:69
Dune::VTK::DataMode dataMode() const
Definition: io/vtkoutputmodule.hh:194
void addField(const Vector &v, const std::string &name, Dumux::Vtk::Precision precision, FieldType fieldType=FieldType::automatic)
Add a scalar or vector valued vtk field.
Definition: io/vtkoutputmodule.hh:123
Dune::VTKWriter< GridView > & writer()
Definition: io/vtkoutputmodule.hh:197
Dune::VTKSequenceWriter< GridView > & sequenceWriter()
Definition: io/vtkoutputmodule.hh:198
const std::string & name() const
Definition: io/vtkoutputmodule.hh:193
const std::vector< Field > & fields() const
Definition: io/vtkoutputmodule.hh:200
virtual ~VtkOutputModuleBase()=default
bool verbose() const
Definition: io/vtkoutputmodule.hh:192
void addField(const Vector &v, const std::string &name, FieldType fieldType=FieldType::automatic)
Add a scalar or vector valued vtk field.
Definition: io/vtkoutputmodule.hh:107
const GridGeometry & gridGeometry() const
Definition: io/vtkoutputmodule.hh:190
A VTK output module to simplify writing dumux simulation data to VTK format.
Definition: io/vtkoutputmodule.hh:305
const auto & problem() const
Definition: io/vtkoutputmodule.hh:383
const GridVariables & gridVariables() const
Definition: io/vtkoutputmodule.hh:384
void addVolumeVariable(std::function< VolVarsVector(const VolumeVariables &)> &&f, const std::string &name)
Definition: io/vtkoutputmodule.hh:375
VV VolumeVariables
export type of the volume variables for the outputfields
Definition: io/vtkoutputmodule.hh:333
void addVolumeVariable(std::function< Scalar(const VolumeVariables &)> &&f, const std::string &name)
Definition: io/vtkoutputmodule.hh:364
void addVelocityOutput(std::shared_ptr< VelocityOutputType > velocityOutput)
Add a velocity output policy.
Definition: io/vtkoutputmodule.hh:358
const VelocityOutput & velocityOutput() const
Definition: io/vtkoutputmodule.hh:392
const SolutionVector & sol() const
Definition: io/vtkoutputmodule.hh:386
const GridGeometry & gridGeometry() const
Definition: io/vtkoutputmodule.hh:385
VtkOutputModule(const GridVariables &gridVariables, const SolutionVector &sol, const std::string &name, const std::string &paramGroup="", Dune::VTK::DataMode dm=Dune::VTK::conforming, bool verbose=true)
Definition: io/vtkoutputmodule.hh:335
const std::vector< VolVarScalarDataInfo > & volVarScalarDataInfo() const
Definition: io/vtkoutputmodule.hh:388
const std::vector< VolVarVectorDataInfo > & volVarVectorDataInfo() const
Definition: io/vtkoutputmodule.hh:389
Velocity output for porous media models.