fvbasediscretization.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 This file is part of the Open Porous Media project (OPM).
5
6 OPM 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 2 of the License, or
9 (at your option) any later version.
10
11 OPM 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 OPM. If not, see <http://www.gnu.org/licenses/>.
18
19 Consult the COPYING file in the top-level source directory of this
20 module for the precise wording of the license and the list of
21 copyright holders.
22*/
28#ifndef EWOMS_FV_BASE_DISCRETIZATION_HH
29#define EWOMS_FV_BASE_DISCRETIZATION_HH
30
31#include <dune/common/fmatrix.hh>
32#include <dune/common/fvector.hh>
33#include <dune/common/version.hh>
34#include <dune/istl/bvector.hh>
35
36#include <opm/material/common/MathToolbox.hpp>
37#include <opm/material/common/Valgrind.hpp>
38#include <opm/material/densead/Math.hpp>
39
55
57
60
65
68
69#include <algorithm>
70#include <array>
71#include <cstddef>
72#include <list>
73#include <memory>
74#include <stdexcept>
75#include <sstream>
76#include <string>
77#include <type_traits>
78#include <utility>
79#include <vector>
80
81namespace Opm {
82
83template<class TypeTag>
84class FvBaseDiscretizationNoAdapt;
85
86template<class TypeTag>
87class FvBaseDiscretization;
88
89} // namespace Opm
90
91namespace Opm::Properties {
92
94template<class TypeTag>
95struct Simulator<TypeTag, TTag::FvBaseDiscretization>
97
99template<class TypeTag>
100struct VertexMapper<TypeTag, TTag::FvBaseDiscretization>
101{ using type = Dune::MultipleCodimMultipleGeomTypeMapper<GetPropType<TypeTag, Properties::GridView>>; };
102
104template<class TypeTag>
106{ using type = Dune::MultipleCodimMultipleGeomTypeMapper<GetPropType<TypeTag, Properties::GridView>>; };
107
109template<class TypeTag>
111{
114
115public:
117};
118
119template<class TypeTag>
122
123template<class TypeTag>
126
127template<class TypeTag>
130
132template<class TypeTag>
135
139template<class TypeTag>
140struct EqVector<TypeTag, TTag::FvBaseDiscretization>
141{
142 using type = Dune::FieldVector<GetPropType<TypeTag, Properties::Scalar>,
143 getPropValue<TypeTag, Properties::NumEq>()>;
144};
145
151template<class TypeTag>
152struct RateVector<TypeTag, TTag::FvBaseDiscretization>
154
158template<class TypeTag>
161
165template<class TypeTag>
166struct Constraints<TypeTag, TTag::FvBaseDiscretization>
168
172template<class TypeTag>
174{ using type = Dune::BlockVector<GetPropType<TypeTag, Properties::EqVector>>; };
175
179template<class TypeTag>
181{ using type = Dune::BlockVector<GetPropType<TypeTag, Properties::EqVector>>; };
182
186template<class TypeTag>
189
193template<class TypeTag>
195{ using type = Dune::BlockVector<GetPropType<TypeTag, Properties::PrimaryVariables>>; };
196
202template<class TypeTag>
205
209template<class TypeTag>
212
213template<class TypeTag>
216
217template<class TypeTag>
220
224template<class TypeTag>
227
228template<class TypeTag>
230{ static constexpr bool value = true; };
231
235template<class TypeTag>
236struct Linearizer<TypeTag, TTag::FvBaseDiscretization>
238
240template<class TypeTag>
242{ static constexpr auto value = Dune::VTK::ascii; };
243
244// disable constraints by default
245template<class TypeTag>
247{ static constexpr bool value = false; };
248
250template<class TypeTag>
252{ static constexpr int value = 2; };
253
256template<class TypeTag>
258{ static constexpr bool value = false; };
259
260// use volumetric residuals is default
261template<class TypeTag>
263{ static constexpr bool value = true; };
264
267template<class TypeTag>
269{ static constexpr bool value = true; };
270
271template <class TypeTag, class MyTypeTag>
273
274#if !HAVE_DUNE_FEM
275template<class TypeTag>
278
279template<class TypeTag>
281{
284};
285#endif
286
287} // namespace Opm::Properties
288
289namespace Opm {
290
296template<class TypeTag>
298{
299 using Implementation = GetPropType<TypeTag, Properties::Model>;
326
329
330 enum {
331 numEq = getPropValue<TypeTag, Properties::NumEq>(),
332 historySize = getPropValue<TypeTag, Properties::TimeDiscHistorySize>(),
333 };
334
335 using IntensiveQuantitiesVector = std::vector<IntensiveQuantities,
336 aligned_allocator<IntensiveQuantities,
337 alignof(IntensiveQuantities)>>;
338
339 using Element = typename GridView::template Codim<0>::Entity;
340 using ElementIterator = typename GridView::template Codim<0>::Iterator;
341
342 using Toolbox = MathToolbox<Evaluation>;
343 using VectorBlock = Dune::FieldVector<Evaluation, numEq>;
344 using EvalEqVector = Dune::FieldVector<Evaluation, numEq>;
345
346 using LocalEvalBlockVector = typename LocalResidual::LocalEvalBlockVector;
347
348public:
350 {
351 protected:
352 SolutionVector blockVector_;
353 public:
354 BlockVectorWrapper(const std::string&, const std::size_t size)
355 : blockVector_(size)
356 {}
357
359
361 {
362 BlockVectorWrapper result("dummy", 3);
363 result.blockVector_[0] = 1.0;
364 result.blockVector_[1] = 2.0;
365 result.blockVector_[2] = 3.0;
366
367 return result;
368 }
369
370 SolutionVector& blockVector()
371 { return blockVector_; }
372
373 const SolutionVector& blockVector() const
374 { return blockVector_; }
375
376 bool operator==(const BlockVectorWrapper& wrapper) const
377 {
378 return std::ranges::equal(this->blockVector_, wrapper.blockVector_);
379 }
380
381 template<class Serializer>
382 void serializeOp(Serializer& serializer)
383 {
384 serializer(blockVector_);
385 }
386 };
387
388private:
391
392public:
393 explicit FvBaseDiscretization(Simulator& simulator)
394 : simulator_(simulator)
395 , gridView_(simulator.gridView())
396 , elementMapper_(gridView_, Dune::mcmgElementLayout())
397 , vertexMapper_(gridView_, Dune::mcmgVertexLayout())
398 , newtonMethod_(simulator)
399 , localLinearizer_(ThreadManager::maxThreads())
400 , linearizer_(std::make_unique<Linearizer>())
401 , enableGridAdaptation_(Parameters::Get<Parameters::EnableGridAdaptation>() )
402 , enableIntensiveQuantityCache_(Parameters::Get<Parameters::EnableIntensiveQuantityCache>())
403 , enableStorageCache_(Parameters::Get<Parameters::EnableStorageCache>())
404 , enableThermodynamicHints_(Parameters::Get<Parameters::EnableThermodynamicHints>())
405 , cachedIntensiveQuantityHistorySize_(static_cast<unsigned>(-1))
406 {
407 const bool isEcfv = std::is_same_v<Discretization, EcfvDiscretization<TypeTag>>;
408 if (enableGridAdaptation_ && !isEcfv) {
409 throw std::invalid_argument("Grid adaptation currently only works for the "
410 "element-centered finite volume discretization (is: " +
411 Dune::className<Discretization>() + ")");
412 }
413
414 PrimaryVariables::init();
415 // Setting up the intensive quantities cache and storage cache is done in finishInit()
416 // and applyInitialSolution() to ensure that the history size is correct.
417 asImp_().registerOutputModules_();
418 }
419
420 // copying a discretization object is not a good idea
422
426 static void registerParameters()
427 {
428 Linearizer::registerParameters();
429 LocalLinearizer::registerParameters();
430 LocalResidual::registerParameters();
431 GradientCalculator::registerParameters();
432 IntensiveQuantities::registerParameters();
433 ExtensiveQuantities::registerParameters();
435 Linearizer::registerParameters();
436 PrimaryVariables::registerParameters();
437 // register runtime parameters of the output modules
439
440 Parameters::Register<Parameters::EnableGridAdaptation>
441 ("Enable adaptive grid refinement/coarsening");
442 Parameters::Register<Parameters::EnableVtkOutput>
443 ("Global switch for turning on writing VTK files");
444 Parameters::Register<Parameters::EnableThermodynamicHints>
445 ("Enable thermodynamic hints");
446 Parameters::Register<Parameters::EnableIntensiveQuantityCache>
447 ("Turn on caching of intensive quantities");
448 Parameters::Register<Parameters::EnableStorageCache>
449 ("Store previous storage terms and avoid re-calculating them.");
450 Parameters::Register<Parameters::OutputDir>
451 ("The directory to which result files are written");
452 }
453
458 {
459 // initialize the volume of the finite volumes to zero
460 const std::size_t numDof = asImp_().numGridDof();
461 dofTotalVolume_.resize(numDof);
462 std::ranges::fill(dofTotalVolume_, 0.0);
463
464 ElementContext elemCtx(simulator_);
465 gridTotalVolume_ = 0.0;
466
467 // iterate through the grid and evaluate the initial condition
468 for (const auto& elem : elements(gridView_)) {
469 // ignore everything which is not in the interior if the
470 // current process' piece of the grid
471 if (elem.partitionType() != Dune::InteriorEntity) {
472 continue;
473 }
474
475 // deal with the current element
476 elemCtx.updateStencil(elem);
477 const auto& stencil = elemCtx.stencil(/*timeIdx=*/0);
478
479 // loop over all element vertices, i.e. sub control volumes
480 for (unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(/*timeIdx=*/0); dofIdx++) {
481 // map the local degree of freedom index to the global one
482 const unsigned globalIdx = elemCtx.globalSpaceIndex(dofIdx, /*timeIdx=*/0);
483
484 const Scalar dofVolume = stencil.subControlVolume(dofIdx).volume();
485 dofTotalVolume_[globalIdx] += dofVolume;
486 gridTotalVolume_ += dofVolume;
487 }
488 }
489
490 // determine which DOFs should be considered to lie fully in the interior of the
491 // local process grid partition: those which do not have a non-zero volume
492 // before taking the peer processes into account...
493 isLocalDof_.resize(numDof);
494 for (unsigned dofIdx = 0; dofIdx < numDof; ++dofIdx) {
495 isLocalDof_[dofIdx] = (dofTotalVolume_[dofIdx] != 0.0);
496 }
497
498 // add the volumes of the DOFs on the process boundaries
499 const auto sumHandle =
500 GridCommHandleFactory::template sumHandle<Scalar>(dofTotalVolume_,
501 asImp_().dofMapper());
502 gridView_.communicate(*sumHandle,
503 Dune::InteriorBorder_All_Interface,
504 Dune::ForwardCommunication);
505
506 // sum up the volumes of the grid partitions
508
509 linearizer_->init(simulator_);
510 for (unsigned threadId = 0; threadId < ThreadManager::maxThreads(); ++threadId) {
511 localLinearizer_[threadId].init(simulator_);
512 }
513
515
516 newtonMethod_.finishInit();
517 }
518
523 { return enableGridAdaptation_; }
524
530 {
531 // first set the whole domain to zero
532 SolutionVector& uCur = asImp_().solution(/*timeIdx=*/0);
533 uCur = Scalar(0.0);
534
535 ElementContext elemCtx(simulator_);
536
537 // iterate through the grid and evaluate the initial condition
538 for (const auto& elem : elements(gridView_)) {
539 // ignore everything which is not in the interior if the
540 // current process' piece of the grid
541 if (elem.partitionType() != Dune::InteriorEntity) {
542 continue;
543 }
544
545 // deal with the current element
546 elemCtx.updateStencil(elem);
547
548 // loop over all element vertices, i.e. sub control volumes
549 for (unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(/*timeIdx=*/0); ++dofIdx) {
550 // map the local degree of freedom index to the global one
551 const unsigned globalIdx = elemCtx.globalSpaceIndex(dofIdx, /*timeIdx=*/0);
552
553 // let the problem do the dirty work of nailing down
554 // the initial solution.
555 simulator_.problem().initial(uCur[globalIdx], elemCtx, dofIdx, /*timeIdx=*/0);
556 asImp_().supplementInitialSolution_(uCur[globalIdx], elemCtx, dofIdx, /*timeIdx=*/0);
557 uCur[globalIdx].checkDefined();
558 }
559 }
560
561 // synchronize the ghost DOFs (if necessary)
562 asImp_().syncOverlap();
563
564 // also set the solutions of the "previous" time steps to the initial solution.
565 for (unsigned timeIdx = 1; timeIdx < historySize; ++timeIdx) {
566 solution(timeIdx) = solution(/*timeIdx=*/0);
567 }
568
569 // Initialize intensive quantities cache now that all problem-specific parameters are available.
570 // This ensures intensiveQuantityHistorySize is correct based on recycleFirstIterationStorage().
571 // TODO: Where this is done should perhaps be changed once finishInit() is refactored.
573
574 simulator_.problem().initialSolutionApplied();
575
576#ifndef NDEBUG
577 for (unsigned timeIdx = 0; timeIdx < historySize; ++timeIdx) {
578 const auto& sol = solution(timeIdx);
579 for (unsigned dofIdx = 0; dofIdx < sol.size(); ++dofIdx) {
580 sol[dofIdx].checkDefined();
581 }
582 }
583#endif // NDEBUG
584 }
585
590 void prefetch(const Element&) const
591 {
592 // do nothing by default
593 }
594
598 NewtonMethod& newtonMethod()
599 { return newtonMethod_; }
600
604 const NewtonMethod& newtonMethod() const
605 { return newtonMethod_; }
606
622 const IntensiveQuantities* thermodynamicHint(unsigned globalIdx, unsigned timeIdx) const
623 {
625 return 0;
626 }
627
628 // the intensive quantities cache doubles as thermodynamic hint
629 return cachedIntensiveQuantities(globalIdx, timeIdx);
630 }
631
643 const IntensiveQuantities* cachedIntensiveQuantities(unsigned globalIdx, unsigned timeIdx) const
644 {
647 !intensiveQuantityCacheUpToDate_[timeIdx][globalIdx]) {
648 return nullptr;
649 }
650
651 // With the storage cache enabled, usually only the
652 // intensive quantities for the most recent time step are
653 // cached. However, this may be false for some Problem
654 // variants, so we should check if the cache exists for
655 // the timeIdx in question.
656 if (timeIdx > 0 && enableStorageCache_ && intensiveQuantityCache_[timeIdx].empty()) {
657 return nullptr;
658 }
659
660 return &intensiveQuantityCache_[timeIdx][globalIdx];
661 }
662
663 const auto& intensiveQuantityCache() const
664 { return intensiveQuantityCache_; }
665
674 void updateCachedIntensiveQuantities(const IntensiveQuantities& intQuants,
675 unsigned globalIdx,
676 unsigned timeIdx) const
677 {
679 return;
680 }
681
682 intensiveQuantityCache_[timeIdx][globalIdx] = intQuants;
683 intensiveQuantityCacheUpToDate_[timeIdx][globalIdx] = true;
684 }
685
695 unsigned timeIdx,
696 bool newValue) const
697 {
699 return;
700 }
701
702 intensiveQuantityCacheUpToDate_[timeIdx][globalIdx] = newValue ? 1 : 0;
703 }
704
710
716 void invalidateIntensiveQuantitiesCache(unsigned timeIdx) const
717 {
719 return;
720 }
721
723 std::ranges::fill(intensiveQuantityCacheUpToDate_[timeIdx], /*value=*/0);
724 }
725 }
726
727 void invalidateAndUpdateIntensiveQuantities(unsigned timeIdx) const
728 {
730
731 // loop over all elements...
732 ThreadedEntityIterator<GridView, /*codim=*/0> threadedElemIt(gridView_);
733#ifdef _OPENMP
734#pragma omp parallel
735#endif
736 {
737 ElementContext elemCtx(simulator_);
738 ElementIterator elemIt = threadedElemIt.beginParallel();
739 for (; !threadedElemIt.isFinished(elemIt); elemIt = threadedElemIt.increment()) {
740 const Element& elem = *elemIt;
741 elemCtx.updatePrimaryStencil(elem);
742 elemCtx.updatePrimaryIntensiveQuantities(timeIdx);
743 }
744 }
745 }
746
747 template <class GridViewType>
748 void invalidateAndUpdateIntensiveQuantities(unsigned timeIdx, const GridViewType& gridView) const
749 {
750 // loop over all elements...
751 ThreadedEntityIterator<GridViewType, /*codim=*/0> threadedElemIt(gridView);
752#ifdef _OPENMP
753#pragma omp parallel
754#endif
755 {
756
757 ElementContext elemCtx(simulator_);
758 auto elemIt = threadedElemIt.beginParallel();
759 for (; !threadedElemIt.isFinished(elemIt); elemIt = threadedElemIt.increment()) {
760 if (elemIt->partitionType() != Dune::InteriorEntity) {
761 continue;
762 }
763 const Element& elem = *elemIt;
764 elemCtx.updatePrimaryStencil(elem);
765 // Mark cache for this element as invalid.
766 const std::size_t numPrimaryDof = elemCtx.numPrimaryDof(timeIdx);
767 for (unsigned dofIdx = 0; dofIdx < numPrimaryDof; ++dofIdx) {
768 const unsigned globalIndex = elemCtx.globalSpaceIndex(dofIdx, timeIdx);
769 setIntensiveQuantitiesCacheEntryValidity(globalIndex, timeIdx, false);
770 }
771 // Update for this element.
772 elemCtx.updatePrimaryIntensiveQuantities(timeIdx);
773 }
774 }
775 }
776
785 void shiftIntensiveQuantityCache(unsigned numSlots = 1)
786 {
787 if (!storeIntensiveQuantities() || numSlots <= 0) {
788 return;
789 }
790
791 if (enableStorageCache() && simulator_.problem().recycleFirstIterationStorage()) {
792 // If the storage term is cached, the intensive quantities of the previous
793 // time steps do not need to be accessed, and we can thus spare ourselves to
794 // copy the objects for the intensive quantities.
795 // However, if the storage term at the start of the timestep cannot be deduced
796 // from the primary variables, we must calculate it from the old intensive
797 // quantities, and need to shift them.
798 return;
799 }
800
801 const unsigned intensiveHistorySize = cachedIntensiveQuantityHistorySize_;
802 for (unsigned timeIdx = 0; timeIdx < intensiveHistorySize - numSlots; ++timeIdx) {
803 intensiveQuantityCache_[timeIdx + numSlots] = intensiveQuantityCache_[timeIdx];
805 }
806
807 // the cache for the most recent time indices do not need to be invalidated
808 // because the solution for them did not change (TODO: that assumes that there is
809 // no post-processing of the solution after a time step! fix it?)
810 }
811
819 { return enableStorageCache_; }
820
829
843 const EqVector& cachedStorage(unsigned globalIdx, unsigned timeIdx) const
844 {
845 if (!enableStorageCache_ ||
846 timeIdx >= historySize ||
847 !storageCacheUpToDate_[timeIdx][globalIdx]) {
848 throw std::logic_error("Cached storage is not available or up to date for the requested "
849 "global index and time index. Make sure storage cache is enabled "
850 "and the entry is valid before calling this method.");
851 }
852
853 return storageCache_[timeIdx][globalIdx];
854 }
855
867 void updateCachedStorage(unsigned globalIdx, unsigned timeIdx, const EqVector& value) const
868 {
869 if (!enableStorageCache_ || timeIdx >= historySize) {
870 return;
871 }
872
873 storageCache_[timeIdx][globalIdx] = value;
874 storageCacheUpToDate_[timeIdx][globalIdx] = 1;
875 }
876
883 bool storageCacheIsUpToDate(unsigned globalIdx, unsigned timeIdx) const
884 {
885 if (!enableStorageCache_ || timeIdx >= historySize) {
886 return false;
887 }
888 return storageCacheUpToDate_[timeIdx][globalIdx] != 0;
889 }
890
897 void invalidateStorageCacheEntry(unsigned globalIdx, unsigned timeIdx) const
898 {
899 if (enableStorageCache_ && timeIdx < historySize) {
900 storageCacheUpToDate_[timeIdx][globalIdx] = 0;
901 }
902 }
903
909 void invalidateStorageCache(unsigned timeIdx) const
910 {
911 if (enableStorageCache_ && timeIdx < historySize) {
912 std::ranges::fill(storageCacheUpToDate_[timeIdx], /*value=*/0);
913 }
914 }
915
927 void shiftStorageCache(unsigned numSlots = 1) const
928 {
929 // If we cannot recycle first iteration storage, it does not make sense to shift the storage cache.
930 if (enableStorageCache_ && !simulator_.problem().recycleFirstIterationStorage()) {
931 for (unsigned timeIdx = 0; timeIdx < historySize - numSlots; ++timeIdx) {
932 storageCache_[timeIdx + numSlots] = storageCache_[timeIdx];
933 storageCacheUpToDate_[timeIdx + numSlots] = storageCacheUpToDate_[timeIdx];
934 }
935
936 // should we invalidate the cache for the most recent time indices? (see shiftIntensiveQuantityCache)
937 }
938 }
939
947 Scalar globalResidual(GlobalEqVector& dest,
948 const SolutionVector& u) const
949 {
950 mutableSolution(/*timeIdx=*/0) = u;
951 const Scalar res = asImp_().globalResidual(dest);
952 mutableSolution(/*timeIdx=*/0) = asImp_().solution(/*timeIdx=*/0);
953 return res;
954 }
955
962 Scalar globalResidual(GlobalEqVector& dest) const
963 {
964 dest = 0;
965
966 std::mutex mutex;
967 ThreadedEntityIterator<GridView, /*codim=*/0> threadedElemIt(gridView_);
968#ifdef _OPENMP
969#pragma omp parallel
970#endif
971 {
972 // Attention: the variables below are thread specific and thus cannot be
973 // moved in front of the #pragma!
974 const unsigned threadId = ThreadManager::threadId();
975 ElementContext elemCtx(simulator_);
976 ElementIterator elemIt = threadedElemIt.beginParallel();
977 LocalEvalBlockVector residual, storageTerm;
978
979 for (; !threadedElemIt.isFinished(elemIt); elemIt = threadedElemIt.increment()) {
980 const Element& elem = *elemIt;
981 if (elem.partitionType() != Dune::InteriorEntity) {
982 continue;
983 }
984
985 elemCtx.updateAll(elem);
986 residual.resize(elemCtx.numDof(/*timeIdx=*/0));
987 storageTerm.resize(elemCtx.numPrimaryDof(/*timeIdx=*/0));
988 asImp_().localResidual(threadId).eval(residual, elemCtx);
989
990 const std::size_t numPrimaryDof = elemCtx.numPrimaryDof(/*timeIdx=*/0);
991 mutex.lock();
992 for (unsigned dofIdx = 0; dofIdx < numPrimaryDof; ++dofIdx) {
993 const unsigned globalI = elemCtx.globalSpaceIndex(dofIdx, /*timeIdx=*/0);
994 for (unsigned eqIdx = 0; eqIdx < numEq; ++ eqIdx) {
995 dest[globalI][eqIdx] += Toolbox::value(residual[dofIdx][eqIdx]);
996 }
997 }
998 mutex.unlock();
999 }
1000 }
1001
1002 // add up the residuals on the process borders
1003 const auto sumHandle =
1004 GridCommHandleFactory::template sumHandle<EqVector>(dest, asImp_().dofMapper());
1005 gridView_.communicate(*sumHandle,
1006 Dune::InteriorBorder_InteriorBorder_Interface,
1007 Dune::ForwardCommunication);
1008
1009 // calculate the square norm of the residual. this is not
1010 // entirely correct, since the residual for the finite volumes
1011 // which are on the boundary are counted once for every
1012 // process. As often in life: shit happens (, we don't care)...
1013 return std::sqrt(asImp_().gridView().comm().sum(dest.two_norm2()));
1014 }
1015
1022 void globalStorage(EqVector& storage, unsigned timeIdx = 0) const
1023 {
1024 storage = 0;
1025
1026 std::mutex mutex;
1027 ThreadedEntityIterator<GridView, /*codim=*/0> threadedElemIt(gridView());
1028#ifdef _OPENMP
1029#pragma omp parallel
1030#endif
1031 {
1032 // Attention: the variables below are thread specific and thus cannot be
1033 // moved in front of the #pragma!
1034 const unsigned threadId = ThreadManager::threadId();
1035 ElementContext elemCtx(simulator_);
1036 ElementIterator elemIt = threadedElemIt.beginParallel();
1037 LocalEvalBlockVector elemStorage;
1038
1039 // in this method, we need to disable the storage cache because we want to
1040 // evaluate the storage term for other time indices than the most recent one
1041 elemCtx.setEnableStorageCache(false);
1042
1043 for (; !threadedElemIt.isFinished(elemIt); elemIt = threadedElemIt.increment()) {
1044 const Element& elem = *elemIt;
1045 if (elem.partitionType() != Dune::InteriorEntity) {
1046 continue; // ignore ghost and overlap elements
1047 }
1048
1049 elemCtx.updateStencil(elem);
1050 elemCtx.updatePrimaryIntensiveQuantities(timeIdx);
1051
1052 const std::size_t numPrimaryDof = elemCtx.numPrimaryDof(timeIdx);
1053 elemStorage.resize(numPrimaryDof);
1054
1055 localResidual(threadId).evalStorage(elemStorage, elemCtx, timeIdx);
1056
1057 mutex.lock();
1058 for (unsigned dofIdx = 0; dofIdx < numPrimaryDof; ++dofIdx) {
1059 for (unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx) {
1060 storage[eqIdx] += Toolbox::value(elemStorage[dofIdx][eqIdx]);
1061 }
1062 }
1063 mutex.unlock();
1064 }
1065 }
1066
1067 storage = gridView_.comm().sum(storage);
1068 }
1069
1077 void checkConservativeness([[maybe_unused]] Scalar tolerance = -1,
1078 [[maybe_unused]] bool verbose = false) const
1079 {
1080#ifndef NDEBUG
1081 Scalar totalBoundaryArea(0.0);
1082 Scalar totalVolume(0.0);
1083 EvalEqVector totalRate(0.0);
1084
1085 // take the newton tolerance times the total volume of the grid if we're not
1086 // given an explicit tolerance...
1087 if (tolerance <= 0) {
1088 tolerance =
1089 simulator_.model().newtonMethod().tolerance() *
1090 simulator_.model().gridTotalVolume() *
1091 1000;
1092 }
1093
1094 // we assume the implicit Euler time discretization for now...
1095 assert(historySize == 2);
1096
1097 EqVector storageBeginTimeStep(0.0);
1098 globalStorage(storageBeginTimeStep, /*timeIdx=*/1);
1099
1100 EqVector storageEndTimeStep(0.0);
1101 globalStorage(storageEndTimeStep, /*timeIdx=*/0);
1102
1103 // calculate the rate at the boundary and the source rate
1104 ElementContext elemCtx(simulator_);
1105 elemCtx.setEnableStorageCache(false);
1106 for (const auto& elem : elements(simulator_.gridView())) {
1107 if (elem.partitionType() != Dune::InteriorEntity) {
1108 continue; // ignore ghost and overlap elements
1109 }
1110
1111 elemCtx.updateAll(elem);
1112
1113 // handle the boundary terms
1114 if (elemCtx.onBoundary()) {
1115 BoundaryContext boundaryCtx(elemCtx);
1116
1117 for (unsigned faceIdx = 0; faceIdx < boundaryCtx.numBoundaryFaces(/*timeIdx=*/0); ++faceIdx) {
1118 BoundaryRateVector values;
1119 simulator_.problem().boundary(values,
1120 boundaryCtx,
1121 faceIdx,
1122 /*timeIdx=*/0);
1123 Valgrind::CheckDefined(values);
1124
1125 const unsigned dofIdx = boundaryCtx.interiorScvIndex(faceIdx, /*timeIdx=*/0);
1126 const auto& insideIntQuants = elemCtx.intensiveQuantities(dofIdx, /*timeIdx=*/0);
1127
1128 const Scalar bfArea =
1129 boundaryCtx.boundarySegmentArea(faceIdx, /*timeIdx=*/0) *
1130 insideIntQuants.extrusionFactor();
1131
1132 for (unsigned i = 0; i < values.size(); ++i) {
1133 values[i] *= bfArea;
1134 }
1135
1136 totalBoundaryArea += bfArea;
1137 for (unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx) {
1138 totalRate[eqIdx] += values[eqIdx];
1139 }
1140 }
1141 }
1142
1143 // deal with the source terms
1144 for (unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(/*timeIdx=*/0); ++dofIdx) {
1145 RateVector values;
1146 simulator_.problem().source(values,
1147 elemCtx,
1148 dofIdx,
1149 /*timeIdx=*/0);
1150 Valgrind::CheckDefined(values);
1151
1152 const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, /*timeIdx=*/0);
1153 Scalar dofVolume =
1154 elemCtx.dofVolume(dofIdx, /*timeIdx=*/0) *
1155 intQuants.extrusionFactor();
1156 for (unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx) {
1157 totalRate[eqIdx] += -dofVolume*Toolbox::value(values[eqIdx]);
1158 }
1159 totalVolume += dofVolume;
1160 }
1161 }
1162
1163 // summarize everything over all processes
1164 const auto& comm = simulator_.gridView().comm();
1165 totalRate = comm.sum(totalRate);
1166 totalBoundaryArea = comm.sum(totalBoundaryArea);
1167 totalVolume = comm.sum(totalVolume);
1168
1169 if (comm.rank() == 0) {
1170 EqVector storageRate = storageBeginTimeStep;
1171 storageRate -= storageEndTimeStep;
1172 storageRate /= simulator_.timeStepSize();
1173 if (verbose) {
1174 std::cout << "storage at beginning of time step: " << storageBeginTimeStep << "\n";
1175 std::cout << "storage at end of time step: " << storageEndTimeStep << "\n";
1176 std::cout << "rate based on storage terms: " << storageRate << "\n";
1177 std::cout << "rate based on source and boundary terms: " << totalRate << "\n";
1178 std::cout << "difference in rates: ";
1179 for (unsigned eqIdx = 0; eqIdx < EqVector::dimension; ++eqIdx) {
1180 std::cout << (storageRate[eqIdx] - Toolbox::value(totalRate[eqIdx])) << " ";
1181 }
1182 std::cout << "\n";
1183 }
1184 for (unsigned eqIdx = 0; eqIdx < EqVector::dimension; ++eqIdx) {
1185 Scalar eps =
1186 (std::abs(storageRate[eqIdx]) + Toolbox::value(totalRate[eqIdx])) * tolerance;
1187 eps = std::max(tolerance, eps);
1188 assert(std::abs(storageRate[eqIdx] - Toolbox::value(totalRate[eqIdx])) <= eps);
1189 }
1190 }
1191#endif // NDEBUG
1192 }
1193
1199 Scalar dofTotalVolume(unsigned globalIdx) const
1200 { return dofTotalVolume_[globalIdx]; }
1201
1207 bool isLocalDof(unsigned globalIdx) const
1208 { return isLocalDof_[globalIdx]; }
1209
1210 size_t numDof() const
1211 { return asImp_().numGridDof(); }
1212
1217 Scalar gridTotalVolume() const
1218 { return gridTotalVolume_; }
1219
1225 const SolutionVector& solution(unsigned timeIdx) const
1226 { return solution_[timeIdx]->blockVector(); }
1227
1231 SolutionVector& solution(unsigned timeIdx)
1232 { return solution_[timeIdx]->blockVector(); }
1233
1234 protected:
1238 SolutionVector& mutableSolution(unsigned timeIdx) const
1239 { return solution_[timeIdx]->blockVector(); }
1240
1241 public:
1246 const Linearizer& linearizer() const
1247 { return *linearizer_; }
1248
1253 Linearizer& linearizer()
1254 { return *linearizer_; }
1255
1264 const LocalLinearizer& localLinearizer(unsigned openMpThreadId) const
1265 { return localLinearizer_[openMpThreadId]; }
1266
1270 LocalLinearizer& localLinearizer(unsigned openMpThreadId)
1271 { return localLinearizer_[openMpThreadId]; }
1272
1276 const LocalResidual& localResidual(unsigned openMpThreadId) const
1277 { return asImp_().localLinearizer(openMpThreadId).localResidual(); }
1278
1282 LocalResidual& localResidual(unsigned openMpThreadId)
1283 { return asImp_().localLinearizer(openMpThreadId).localResidual(); }
1284
1292 Scalar primaryVarWeight(unsigned globalDofIdx, unsigned pvIdx) const
1293 {
1294 const Scalar absPv = std::abs(asImp_().solution(/*timeIdx=*/1)[globalDofIdx][pvIdx]);
1295 return 1.0 / std::max(absPv, 1.0);
1296 }
1297
1304 Scalar eqWeight(unsigned, unsigned) const
1305 { return 1.0; }
1306
1316 Scalar relativeDofError(unsigned vertexIdx,
1317 const PrimaryVariables& pv1,
1318 const PrimaryVariables& pv2) const
1319 {
1320 Scalar result = 0.0;
1321 for (unsigned j = 0; j < numEq; ++j) {
1322 const Scalar weight = asImp_().primaryVarWeight(vertexIdx, j);
1323 const Scalar eqErr = std::abs((pv1[j] - pv2[j])*weight);
1324 //Scalar eqErr = std::abs(pv1[j] - pv2[j]);
1325 //eqErr *= std::max<Scalar>(1.0, std::abs(pv1[j] + pv2[j])/2);
1326
1327 result = std::max(result, eqErr);
1328 }
1329 return result;
1330 }
1331
1337 bool update()
1338 {
1339 const TimerGuard prePostProcessGuard(prePostProcessTimer_);
1340
1341#ifndef NDEBUG
1342 for (unsigned timeIdx = 0; timeIdx < historySize; ++timeIdx) {
1343 // Make sure that the primary variables are defined. Note that because of padding
1344 // bytes, we can't just simply ask valgrind to check the whole solution vectors
1345 // for definedness...
1346 for (std::size_t i = 0; i < asImp_().solution(/*timeIdx=*/0).size(); ++i) {
1347 asImp_().solution(timeIdx)[i].checkDefined();
1348 }
1349 }
1350#endif // NDEBUG
1351
1352 // make sure all timers are prestine
1355 solveTimer_.halt();
1357
1359 asImp_().updateBegin();
1361
1362 bool converged = false;
1363
1364 try {
1365 converged = newtonMethod_.apply();
1366 }
1367 catch(...) {
1368 prePostProcessTimer_ += newtonMethod_.prePostProcessTimer();
1369 linearizeTimer_ += newtonMethod_.linearizeTimer();
1370 solveTimer_ += newtonMethod_.solveTimer();
1371 updateTimer_ += newtonMethod_.updateTimer();
1372
1373 throw;
1374 }
1375
1376#ifndef NDEBUG
1377 for (unsigned timeIdx = 0; timeIdx < historySize; ++timeIdx) {
1378 // Make sure that the primary variables are defined. Note that because of padding
1379 // bytes, we can't just simply ask valgrind to check the whole solution vectors
1380 // for definedness...
1381 for (std::size_t i = 0; i < asImp_().solution(/*timeIdx=*/0).size(); ++i) {
1382 asImp_().solution(timeIdx)[i].checkDefined();
1383 }
1384 }
1385#endif // NDEBUG
1386
1387 prePostProcessTimer_ += newtonMethod_.prePostProcessTimer();
1388 linearizeTimer_ += newtonMethod_.linearizeTimer();
1389 solveTimer_ += newtonMethod_.solveTimer();
1390 updateTimer_ += newtonMethod_.updateTimer();
1391
1393 if (converged) {
1394 asImp_().updateSuccessful();
1395 }
1396 else {
1397 asImp_().updateFailed();
1398 }
1400
1401#ifndef NDEBUG
1402 for (unsigned timeIdx = 0; timeIdx < historySize; ++timeIdx) {
1403 // Make sure that the primary variables are defined. Note that because of padding
1404 // bytes, we can't just simply ask valgrind to check the whole solution vectors
1405 // for definedness...
1406 for (std::size_t i = 0; i < asImp_().solution(/*timeIdx=*/0).size(); ++i) {
1407 asImp_().solution(timeIdx)[i].checkDefined();
1408 }
1409 }
1410#endif // NDEBUG
1411
1412 return converged;
1413 }
1414
1423 {}
1424
1431 {}
1432
1438 {}
1439
1444 {
1445 throw std::invalid_argument("Grid adaptation need to be implemented for "
1446 "specific settings of grid and function spaces");
1447 }
1448
1455 {
1456 // Reset the current solution to the one of the
1457 // previous time step so that we can start the next
1458 // update at a physically meaningful solution.
1459 solution(/*timeIdx=*/0) = solution(/*timeIdx=*/1);
1461
1462#ifndef NDEBUG
1463 for (unsigned timeIdx = 0; timeIdx < historySize; ++timeIdx) {
1464 // Make sure that the primary variables are defined. Note that because of padding
1465 // bytes, we can't just simply ask valgrind to check the whole solution vectors
1466 // for definedness...
1467 for (std::size_t i = 0; i < asImp_().solution(/*timeIdx=*/0).size(); ++i) {
1468 asImp_().solution(timeIdx)[i].checkDefined();
1469 }
1470 }
1471#endif // NDEBUG
1472 }
1473
1482 {
1483 // at this point we can adapt the grid
1484 if (this->enableGridAdaptation_) {
1485 asImp_().adaptGrid();
1486 }
1487
1488 // make the current solution the previous one.
1489 solution(/*timeIdx=*/1) = solution(/*timeIdx=*/0);
1490
1491 // shift the storage cache by one position in the history
1492 asImp_().shiftStorageCache(/*numSlots=*/1);
1493
1494 // shift the intensive quantities cache by one position in the
1495 // history
1496 asImp_().shiftIntensiveQuantityCache(/*numSlots=*/1);
1497 }
1498
1506 template <class Restarter>
1507 void serialize(Restarter&)
1508 {
1509 throw std::runtime_error("Not implemented: The discretization chosen for this problem "
1510 "does not support restart files. (serialize() method unimplemented)");
1511 }
1512
1520 template <class Restarter>
1521 void deserialize(Restarter&)
1522 {
1523 throw std::runtime_error("Not implemented: The discretization chosen for this problem "
1524 "does not support restart files. (deserialize() method unimplemented)");
1525 }
1526
1535 template <class DofEntity>
1536 void serializeEntity(std::ostream& outstream,
1537 const DofEntity& dof)
1538 {
1539 const unsigned dofIdx = static_cast<unsigned>(asImp_().dofMapper().index(dof));
1540
1541 // write phase state
1542 if (!outstream.good()) {
1543 throw std::runtime_error("Could not serialize degree of freedom " +
1544 std::to_string(dofIdx));
1545 }
1546
1547 for (unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx) {
1548 outstream << solution(/*timeIdx=*/0)[dofIdx][eqIdx] << " ";
1549 }
1550 }
1551
1560 template <class DofEntity>
1561 void deserializeEntity(std::istream& instream,
1562 const DofEntity& dof)
1563 {
1564 const unsigned dofIdx = static_cast<unsigned>(asImp_().dofMapper().index(dof));
1565
1566 for (unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx) {
1567 if (!instream.good()) {
1568 throw std::runtime_error("Could not deserialize degree of freedom " +
1569 std::to_string(dofIdx));
1570 }
1571 instream >> solution(/*timeIdx=*/0)[dofIdx][eqIdx];
1572 }
1573 }
1574
1578 std::size_t numGridDof() const
1579 { throw std::logic_error("The discretization class must implement the numGridDof() method!"); }
1580
1584 std::size_t numAuxiliaryDof() const
1585 {
1586 return std::accumulate(auxEqModules_.begin(), auxEqModules_.end(),
1587 std::size_t{0},
1588 [](const auto acc, const auto& mod)
1589 { return acc + mod->numDofs(); });
1590 }
1591
1595 std::size_t numTotalDof() const
1596 { return asImp_().numGridDof() + numAuxiliaryDof(); }
1597
1602 const DofMapper& dofMapper() const
1603 { throw std::logic_error("The discretization class must implement the dofMapper() method!"); }
1604
1608 const VertexMapper& vertexMapper() const
1609 { return vertexMapper_; }
1610
1614 const ElementMapper& elementMapper() const
1615 { return elementMapper_; }
1616
1622 {
1623 linearizer_ = std::make_unique<Linearizer>();
1624 linearizer_->init(simulator_);
1625 }
1626
1630 static std::string discretizationName()
1631 { return ""; }
1632
1638 std::string primaryVarName(unsigned pvIdx) const
1639 {
1640 std::ostringstream oss;
1641 oss << "primary variable_" << pvIdx;
1642 return oss.str();
1643 }
1644
1650 std::string eqName(unsigned eqIdx) const
1651 {
1652 std::ostringstream oss;
1653 oss << "equation_" << eqIdx;
1654 return oss.str();
1655 }
1656
1663 void updatePVWeights(const ElementContext&) const
1664 {}
1665
1669 void addOutputModule(std::unique_ptr<BaseOutputModule<TypeTag>> newModule)
1670 { outputModules_.push_back(std::move(newModule)); }
1671
1680 template <class VtkMultiWriter>
1682 const SolutionVector& u,
1683 const GlobalEqVector& deltaU) const
1684 {
1685 using ScalarBuffer = std::vector<double>;
1686
1687 GlobalEqVector globalResid(u.size());
1688 asImp_().globalResidual(globalResid, u);
1689
1690 // create the required scalar fields
1691 const std::size_t numDof = asImp_().numGridDof();
1692
1693 // global defect of the two auxiliary equations
1694 std::array<ScalarBuffer*, numEq> def;
1695 std::array<ScalarBuffer*, numEq> delta;
1696 std::array<ScalarBuffer*, numEq> priVars;
1697 std::array<ScalarBuffer*, numEq> priVarWeight;
1698 ScalarBuffer* relError = writer.allocateManagedScalarBuffer(numDof);
1699 ScalarBuffer* normalizedRelError = writer.allocateManagedScalarBuffer(numDof);
1700 for (unsigned pvIdx = 0; pvIdx < numEq; ++pvIdx) {
1701 priVars[pvIdx] = writer.allocateManagedScalarBuffer(numDof);
1702 priVarWeight[pvIdx] = writer.allocateManagedScalarBuffer(numDof);
1703 delta[pvIdx] = writer.allocateManagedScalarBuffer(numDof);
1704 def[pvIdx] = writer.allocateManagedScalarBuffer(numDof);
1705 }
1706
1707 Scalar minRelErr = 1e30;
1708 Scalar maxRelErr = -1e30;
1709 for (unsigned globalIdx = 0; globalIdx < numDof; ++ globalIdx) {
1710 for (unsigned pvIdx = 0; pvIdx < numEq; ++pvIdx) {
1711 (*priVars[pvIdx])[globalIdx] = u[globalIdx][pvIdx];
1712 (*priVarWeight[pvIdx])[globalIdx] = asImp_().primaryVarWeight(globalIdx, pvIdx);
1713 (*delta[pvIdx])[globalIdx] = - deltaU[globalIdx][pvIdx];
1714 (*def[pvIdx])[globalIdx] = globalResid[globalIdx][pvIdx];
1715 }
1716
1717 PrimaryVariables uOld(u[globalIdx]);
1718 PrimaryVariables uNew(uOld);
1719 uNew -= deltaU[globalIdx];
1720
1721 const Scalar err = asImp_().relativeDofError(globalIdx, uOld, uNew);
1722 (*relError)[globalIdx] = err;
1723 (*normalizedRelError)[globalIdx] = err;
1724 minRelErr = std::min(err, minRelErr);
1725 maxRelErr = std::max(err, maxRelErr);
1726 }
1727
1728 // do the normalization of the relative error
1729 const Scalar alpha = std::max(Scalar{1e-20},
1730 std::max(std::abs(maxRelErr),
1731 std::abs(minRelErr)));
1732 for (unsigned globalIdx = 0; globalIdx < numDof; ++globalIdx) {
1733 (*normalizedRelError)[globalIdx] /= alpha;
1734 }
1735
1736 DiscBaseOutputModule::attachScalarDofData_(writer, *relError, "relative error");
1737 DiscBaseOutputModule::attachScalarDofData_(writer, *normalizedRelError, "normalized relative error");
1738
1739 for (unsigned i = 0; i < numEq; ++i) {
1740 std::ostringstream oss;
1741 oss.str(""); oss << "priVar_" << asImp_().primaryVarName(i);
1742 DiscBaseOutputModule::attachScalarDofData_(writer,
1743 *priVars[i],
1744 oss.str());
1745
1746 oss.str(""); oss << "delta_" << asImp_().primaryVarName(i);
1747 DiscBaseOutputModule::attachScalarDofData_(writer,
1748 *delta[i],
1749 oss.str());
1750
1751 oss.str(""); oss << "weight_" << asImp_().primaryVarName(i);
1752 DiscBaseOutputModule::attachScalarDofData_(writer,
1753 *priVarWeight[i],
1754 oss.str());
1755
1756 oss.str(""); oss << "defect_" << asImp_().eqName(i);
1757 DiscBaseOutputModule::attachScalarDofData_(writer,
1758 *def[i],
1759 oss.str());
1760 }
1761
1762 asImp_().prepareOutputFields();
1763 asImp_().appendOutputFields(writer);
1764 }
1765
1771 {
1772 const bool needFullContextUpdate =
1773 std::ranges::any_of(outputModules_,
1774 [](const auto& mod)
1775 { return mod->needExtensiveQuantities(); });
1776 std::ranges::for_each(outputModules_,
1777 [](auto& mod) { mod->allocBuffers(); });
1778
1779 // iterate over grid
1780 ThreadedEntityIterator<GridView, /*codim=*/0> threadedElemIt(gridView());
1781#ifdef _OPENMP
1782#pragma omp parallel
1783#endif
1784 {
1785 ElementContext elemCtx(simulator_);
1786 ElementIterator elemIt = threadedElemIt.beginParallel();
1787 for (; !threadedElemIt.isFinished(elemIt); elemIt = threadedElemIt.increment()) {
1788 const auto& elem = *elemIt;
1789 if (elem.partitionType() != Dune::InteriorEntity) {
1790 // ignore non-interior entities
1791 continue;
1792 }
1793
1794 if (needFullContextUpdate) {
1795 elemCtx.updateAll(elem);
1796 }
1797 else {
1798 elemCtx.updatePrimaryStencil(elem);
1799 elemCtx.updatePrimaryIntensiveQuantities(/*timeIdx=*/0);
1800 }
1801
1802 std::ranges::for_each(outputModules_,
1803 [&elemCtx](auto& mod) { mod->processElement(elemCtx); });
1804 }
1805 }
1806 }
1807
1813 {
1814 std::ranges::for_each(outputModules_,
1815 [&writer](auto& mod) { mod->commitBuffers(writer); });
1816 }
1817
1821 const GridView& gridView() const
1822 { return gridView_; }
1823
1836 {
1837 auxMod->setDofOffset(numTotalDof());
1838 auxEqModules_.push_back(auxMod);
1839
1840 // resize the solutions
1841 if (enableGridAdaptation_ && !std::is_same_v<DiscreteFunction, BlockVectorWrapper>) {
1842 throw std::invalid_argument("Problems which require auxiliary modules cannot be used in"
1843 " conjunction with dune-fem");
1844 }
1845
1846 const std::size_t numDof = numTotalDof();
1847 for (unsigned timeIdx = 0; timeIdx < historySize; ++timeIdx) {
1848 solution(timeIdx).resize(numDof);
1849 }
1850
1851 auxMod->applyInitial();
1852 }
1853
1860 {
1861 auxEqModules_.clear();
1862 linearizer_->eraseMatrix();
1863 newtonMethod_.eraseMatrix();
1864 }
1865
1869 std::size_t numAuxiliaryModules() const
1870 { return auxEqModules_.size(); }
1871
1876 { return auxEqModules_[auxEqModIdx]; }
1877
1881 const BaseAuxiliaryModule<TypeTag>* auxiliaryModule(unsigned auxEqModIdx) const
1882 { return auxEqModules_[auxEqModIdx]; }
1883
1889
1891 { return prePostProcessTimer_; }
1892
1893 const Timer& linearizeTimer() const
1894 { return linearizeTimer_; }
1895
1896 const Timer& solveTimer() const
1897 { return solveTimer_; }
1898
1899 const Timer& updateTimer() const
1900 { return updateTimer_; }
1901
1902 template<class Serializer>
1903 void serializeOp(Serializer& serializer)
1904 {
1906 using Helper = typename BaseDiscretization::template SerializeHelper<Serializer>;
1907 Helper::serializeOp(serializer, solution_);
1908 }
1909
1910 bool operator==(const FvBaseDiscretization& rhs) const
1911 {
1912 return std::ranges::equal(this->solution_, rhs.solution_,
1913 [](const auto& x, const auto& y)
1914 { return *x == *y; });
1915 }
1916
1917protected:
1919 {
1920 // allocate the storage cache
1921 if (enableStorageCache()) {
1922 const std::size_t numDof = asImp_().numGridDof();
1923 for (unsigned timeIdx = 0; timeIdx < historySize; ++timeIdx) {
1924 storageCache_[timeIdx].resize(numDof);
1925 storageCacheUpToDate_[timeIdx].resize(numDof, /*value=*/0);
1926 }
1927 }
1928
1929 // allocate the intensive quantities cache
1931 const std::size_t numDof = asImp_().numGridDof();
1932 cachedIntensiveQuantityHistorySize_ = simulator_.problem().intensiveQuantityHistorySize();
1933 const unsigned intensiveHistorySize = cachedIntensiveQuantityHistorySize_;
1934
1935 // resize the vectors based on runtime history size
1936 intensiveQuantityCache_.resize(intensiveHistorySize);
1937 intensiveQuantityCacheUpToDate_.resize(intensiveHistorySize);
1938
1939 for(unsigned timeIdx = 0; timeIdx < intensiveHistorySize; ++timeIdx) {
1940 intensiveQuantityCache_[timeIdx].resize(numDof);
1941 intensiveQuantityCacheUpToDate_[timeIdx].resize(numDof);
1943 }
1944 }
1945 }
1946
1947 template <class Context>
1948 void supplementInitialSolution_(PrimaryVariables&,
1949 const Context&,
1950 unsigned,
1951 unsigned)
1952 {}
1953
1962 {
1963 // add the output modules available on all model
1964 this->outputModules_.push_back(std::make_unique<VtkPrimaryVarsModule<TypeTag>>(simulator_));
1965 }
1966
1970 LocalResidual& localResidual_()
1971 { return localLinearizer_.localResidual(); }
1972
1976 bool verbose_() const
1977 { return gridView_.comm().rank() == 0; }
1978
1979 Implementation& asImp_()
1980 { return *static_cast<Implementation*>(this); }
1981
1982 const Implementation& asImp_() const
1983 { return *static_cast<const Implementation*>(this); }
1984
1985 // the problem we want to solve. defines the constitutive
1986 // relations, matxerial laws, etc.
1987 Simulator& simulator_;
1988
1989 // the representation of the spatial domain of the problem
1990 GridView gridView_;
1991
1992 // the mappers for element and vertex entities to global indices
1993 ElementMapper elementMapper_;
1994 VertexMapper vertexMapper_;
1995
1996 // a vector with all auxiliary equations to be considered
1997 std::vector<BaseAuxiliaryModule<TypeTag>*> auxEqModules_;
1998
1999 NewtonMethod newtonMethod_;
2000
2005
2006 // calculates the local jacobian matrix for a given element
2007 std::vector<LocalLinearizer> localLinearizer_;
2008 // Linearizes the problem at the current time step using the
2009 // local jacobian
2010 std::unique_ptr<Linearizer> linearizer_;
2011
2012 // cur is the current iterative solution, prev the converged
2013 // solution of the previous time step
2014 mutable std::vector<IntensiveQuantitiesVector> intensiveQuantityCache_;
2015
2016 // while these are logically bools, concurrent writes to vector<bool> are not thread safe.
2017 mutable std::vector<std::vector<unsigned char>> intensiveQuantityCacheUpToDate_;
2018
2019 std::array<std::unique_ptr<DiscreteFunction>, historySize> solution_;
2020
2021 std::list<std::unique_ptr<BaseOutputModule<TypeTag>>> outputModules_;
2022
2024 std::vector<Scalar> dofTotalVolume_;
2025 std::vector<bool> isLocalDof_;
2026
2027 mutable std::array<GlobalEqVector, historySize> storageCache_;
2028
2029 // while these are logically bools, concurrent writes to vector<bool> are not thread safe.
2030 mutable std::array<std::vector<unsigned char>, historySize> storageCacheUpToDate_;
2031
2036
2038};
2039
2045template<class TypeTag>
2047{
2051
2052 static constexpr unsigned historySize = getPropValue<TypeTag, Properties::TimeDiscHistorySize>();
2053
2054public:
2055 template<class Serializer>
2057 {
2058 template<class SolutionType>
2059 static void serializeOp(Serializer& serializer,
2060 SolutionType& solution)
2061 {
2062 for (auto& sol : solution) {
2063 serializer(*sol);
2064 }
2065 }
2066 };
2067
2068 explicit FvBaseDiscretizationNoAdapt(Simulator& simulator)
2069 : ParentType(simulator)
2070 {
2071 if (this->enableGridAdaptation_) {
2072 throw std::invalid_argument("Grid adaptation need to use"
2073 " BaseDiscretization = FvBaseDiscretizationFemAdapt"
2074 " which currently requires the presence of the"
2075 " dune-fem module");
2076 }
2077 const std::size_t numDof = this->asImp_().numGridDof();
2078 for (unsigned timeIdx = 0; timeIdx < historySize; ++timeIdx) {
2079 this->solution_[timeIdx] = std::make_unique<DiscreteFunction>("solution", numDof);
2080 }
2081 }
2082};
2083
2084} // namespace Opm
2085
2086#endif // EWOMS_FV_BASE_DISCRETIZATION_HH
This is a stand-alone version of boost::alignment::aligned_allocator from Boost 1....
Base class for specifying auxiliary equations.
Definition: baseauxiliarymodule.hh:56
virtual void applyInitial()=0
Set the initial condition of the auxiliary module in the solution vector.
void setDofOffset(int value)
Set the offset in the global system of equations for the first degree of freedom of this auxiliary mo...
Definition: baseauxiliarymodule.hh:78
The base class for writer modules.
Definition: baseoutputmodule.hh:68
The base class for all output writers.
Definition: baseoutputwriter.hh:46
Represents all quantities which available on boundary segments.
Definition: fvbaseboundarycontext.hh:46
Represents all quantities which available for calculating constraints.
Definition: fvbaseconstraintscontext.hh:44
Class to specify constraints for a finite volume spatial discretization.
Definition: fvbaseconstraints.hh:48
Definition: fvbasediscretization.hh:350
const SolutionVector & blockVector() const
Definition: fvbasediscretization.hh:373
SolutionVector blockVector_
Definition: fvbasediscretization.hh:352
void serializeOp(Serializer &serializer)
Definition: fvbasediscretization.hh:382
static BlockVectorWrapper serializationTestObject()
Definition: fvbasediscretization.hh:360
SolutionVector & blockVector()
Definition: fvbasediscretization.hh:370
bool operator==(const BlockVectorWrapper &wrapper) const
Definition: fvbasediscretization.hh:376
BlockVectorWrapper(const std::string &, const std::size_t size)
Definition: fvbasediscretization.hh:354
The base class for the finite volume discretization schemes without adaptation.
Definition: fvbasediscretization.hh:2047
FvBaseDiscretizationNoAdapt(Simulator &simulator)
Definition: fvbasediscretization.hh:2068
The base class for the finite volume discretization schemes.
Definition: fvbasediscretization.hh:298
Timer linearizeTimer_
Definition: fvbasediscretization.hh:2002
std::vector< IntensiveQuantitiesVector > intensiveQuantityCache_
Definition: fvbasediscretization.hh:2014
LocalLinearizer & localLinearizer(unsigned openMpThreadId)
Definition: fvbasediscretization.hh:1270
void prepareOutputFields() const
Prepare the quantities relevant for the current solution to be appended to the output writers.
Definition: fvbasediscretization.hh:1770
void shiftIntensiveQuantityCache(unsigned numSlots=1)
Move the intensive quantities for a given time index to the back.
Definition: fvbasediscretization.hh:785
void invalidateAndUpdateIntensiveQuantities(unsigned timeIdx) const
Definition: fvbasediscretization.hh:727
void adaptGrid()
Called by the update() method when the grid should be refined.
Definition: fvbasediscretization.hh:1443
std::vector< BaseAuxiliaryModule< TypeTag > * > auxEqModules_
Definition: fvbasediscretization.hh:1997
const Implementation & asImp_() const
Definition: fvbasediscretization.hh:1982
void addAuxiliaryModule(BaseAuxiliaryModule< TypeTag > *auxMod)
Add a module for an auxiliary equation.
Definition: fvbasediscretization.hh:1835
void setIntensiveQuantitiesCacheEntryValidity(unsigned globalIdx, unsigned timeIdx, bool newValue) const
Invalidate the cache for a given intensive quantities object.
Definition: fvbasediscretization.hh:694
void finishInit()
Apply the initial conditions to the model.
Definition: fvbasediscretization.hh:457
void prefetch(const Element &) const
Allows to improve the performance by prefetching all data which is associated with a given element.
Definition: fvbasediscretization.hh:590
bool enableStorageCache_
Definition: fvbasediscretization.hh:2034
void resizeAndResetIntensiveQuantitiesCache_()
Definition: fvbasediscretization.hh:1918
std::vector< Scalar > dofTotalVolume_
Definition: fvbasediscretization.hh:2024
void updateSuccessful()
Called by the update() method if it was successful.
Definition: fvbasediscretization.hh:1437
static std::string discretizationName()
Returns a string of discretization's human-readable name.
Definition: fvbasediscretization.hh:1630
unsigned cachedIntensiveQuantityHistorySize() const
Get the cached intensive quantity history size.
Definition: fvbasediscretization.hh:708
BaseAuxiliaryModule< TypeTag > * auxiliaryModule(unsigned auxEqModIdx)
Returns a given module for auxiliary equations.
Definition: fvbasediscretization.hh:1875
bool isLocalDof(unsigned globalIdx) const
Returns if the overlap of the volume ofa degree of freedom is non-zero.
Definition: fvbasediscretization.hh:1207
std::size_t numAuxiliaryModules() const
Returns the number of modules for auxiliary equations.
Definition: fvbasediscretization.hh:1869
bool operator==(const FvBaseDiscretization &rhs) const
Definition: fvbasediscretization.hh:1910
void serializeOp(Serializer &serializer)
Definition: fvbasediscretization.hh:1903
std::vector< bool > isLocalDof_
Definition: fvbasediscretization.hh:2025
LocalResidual & localResidual_()
Reference to the local residal object.
Definition: fvbasediscretization.hh:1970
void registerOutputModules_()
Register all output modules which make sense for the model.
Definition: fvbasediscretization.hh:1961
bool enableGridAdaptation() const
Returns whether the grid ought to be adapted to the solution during the simulation.
Definition: fvbasediscretization.hh:522
const NewtonMethod & newtonMethod() const
Returns the newton method object.
Definition: fvbasediscretization.hh:604
SolutionVector & mutableSolution(unsigned timeIdx) const
Definition: fvbasediscretization.hh:1238
void advanceTimeLevel()
Called by the problem if a time integration was successful, post processing of the solution is done a...
Definition: fvbasediscretization.hh:1481
NewtonMethod & newtonMethod()
Returns the newton method object.
Definition: fvbasediscretization.hh:598
const VertexMapper & vertexMapper() const
Returns the mapper for vertices to indices.
Definition: fvbasediscretization.hh:1608
const EqVector & cachedStorage(unsigned globalIdx, unsigned timeIdx) const
Retrieve an entry of the cache for the storage term.
Definition: fvbasediscretization.hh:843
void updatePVWeights(const ElementContext &) const
Update the weights of all primary variables within an element given the complete set of intensive qua...
Definition: fvbasediscretization.hh:1663
const Timer & solveTimer() const
Definition: fvbasediscretization.hh:1896
void updateFailed()
Called by the update() method if it was unsuccessful. This is primary a hook which the actual model c...
Definition: fvbasediscretization.hh:1454
void updateBegin()
Called by the update() method before it tries to apply the newton method. This is primary a hook whic...
Definition: fvbasediscretization.hh:1430
FvBaseDiscretization(const FvBaseDiscretization &)=delete
Scalar globalResidual(GlobalEqVector &dest) const
Compute the global residual for the current solution vector.
Definition: fvbasediscretization.hh:962
LocalResidual & localResidual(unsigned openMpThreadId)
Definition: fvbasediscretization.hh:1282
void serializeEntity(std::ostream &outstream, const DofEntity &dof)
Write the current solution for a degree of freedom to a restart file.
Definition: fvbasediscretization.hh:1536
void setEnableStorageCache(bool enableStorageCache)
Set the value of enable storage cache.
Definition: fvbasediscretization.hh:827
std::string eqName(unsigned eqIdx) const
Given an equation index, return a human readable name.
Definition: fvbasediscretization.hh:1650
Scalar eqWeight(unsigned, unsigned) const
Returns the relative weight of an equation.
Definition: fvbasediscretization.hh:1304
std::array< std::vector< unsigned char >, historySize > storageCacheUpToDate_
Definition: fvbasediscretization.hh:2030
const Timer & prePostProcessTimer() const
Definition: fvbasediscretization.hh:1890
Scalar primaryVarWeight(unsigned globalDofIdx, unsigned pvIdx) const
Returns the relative weight of a primary variable for calculating relative errors.
Definition: fvbasediscretization.hh:1292
void deserialize(Restarter &)
Deserializes the state of the model.
Definition: fvbasediscretization.hh:1521
void checkConservativeness(Scalar tolerance=-1, bool verbose=false) const
Ensure that the difference between the storage terms of the last and of the current time step is cons...
Definition: fvbasediscretization.hh:1077
Scalar gridTotalVolume() const
Returns the volume of the whole grid which represents the spatial domain.
Definition: fvbasediscretization.hh:1217
Timer updateTimer_
Definition: fvbasediscretization.hh:2004
FvBaseDiscretization(Simulator &simulator)
Definition: fvbasediscretization.hh:393
const IntensiveQuantities * thermodynamicHint(unsigned globalIdx, unsigned timeIdx) const
Return the thermodynamic hint for a entity on the grid at given time.
Definition: fvbasediscretization.hh:622
bool storageCacheIsUpToDate(unsigned globalIdx, unsigned timeIdx) const
Returns true if the storage cache entry for a given DOF and time index is up to date.
Definition: fvbasediscretization.hh:883
const Timer & updateTimer() const
Definition: fvbasediscretization.hh:1899
const Linearizer & linearizer() const
Returns the operator linearizer for the global jacobian of the problem.
Definition: fvbasediscretization.hh:1246
void updateCachedStorage(unsigned globalIdx, unsigned timeIdx, const EqVector &value) const
Set an entry of the cache for the storage term.
Definition: fvbasediscretization.hh:867
void addConvergenceVtkFields(VtkMultiWriter &writer, const SolutionVector &u, const GlobalEqVector &deltaU) const
Add the vector fields for analysing the convergence of the newton method to the a VTK writer.
Definition: fvbasediscretization.hh:1681
Scalar relativeDofError(unsigned vertexIdx, const PrimaryVariables &pv1, const PrimaryVariables &pv2) const
Returns the relative error between two vectors of primary variables.
Definition: fvbasediscretization.hh:1316
bool enableGridAdaptation_
Definition: fvbasediscretization.hh:2032
Scalar globalResidual(GlobalEqVector &dest, const SolutionVector &u) const
Compute the global residual for an arbitrary solution vector.
Definition: fvbasediscretization.hh:947
SolutionVector & solution(unsigned timeIdx)
Definition: fvbasediscretization.hh:1231
std::array< GlobalEqVector, historySize > storageCache_
Definition: fvbasediscretization.hh:2027
Timer prePostProcessTimer_
Definition: fvbasediscretization.hh:2001
void deserializeEntity(std::istream &instream, const DofEntity &dof)
Reads the current solution variables for a degree of freedom from a restart file.
Definition: fvbasediscretization.hh:1561
Timer solveTimer_
Definition: fvbasediscretization.hh:2003
void supplementInitialSolution_(PrimaryVariables &, const Context &, unsigned, unsigned)
Definition: fvbasediscretization.hh:1948
const LocalLinearizer & localLinearizer(unsigned openMpThreadId) const
Returns the local jacobian which calculates the local stiffness matrix for an arbitrary element.
Definition: fvbasediscretization.hh:1264
std::array< std::unique_ptr< DiscreteFunction >, historySize > solution_
Definition: fvbasediscretization.hh:2019
unsigned cachedIntensiveQuantityHistorySize_
Definition: fvbasediscretization.hh:2037
const Timer & linearizeTimer() const
Definition: fvbasediscretization.hh:1893
void invalidateAndUpdateIntensiveQuantities(unsigned timeIdx, const GridViewType &gridView) const
Definition: fvbasediscretization.hh:748
bool update()
Try to progress the model to the next timestep.
Definition: fvbasediscretization.hh:1337
const auto & intensiveQuantityCache() const
Definition: fvbasediscretization.hh:663
std::size_t numAuxiliaryDof() const
Returns the number of degrees of freedom (DOFs) of the auxiliary equations.
Definition: fvbasediscretization.hh:1584
void clearAuxiliaryModules()
Causes the list of auxiliary equations to be cleared.
Definition: fvbasediscretization.hh:1859
bool enableIntensiveQuantityCache_
Definition: fvbasediscretization.hh:2033
std::unique_ptr< Linearizer > linearizer_
Definition: fvbasediscretization.hh:2010
const ElementMapper & elementMapper() const
Returns the mapper for elements to indices.
Definition: fvbasediscretization.hh:1614
void syncOverlap()
Syncronize the values of the primary variables on the degrees of freedom that overlap with the neighb...
Definition: fvbasediscretization.hh:1422
void appendOutputFields(BaseOutputWriter &writer) const
Append the quantities relevant for the current solution to an output writer.
Definition: fvbasediscretization.hh:1812
std::list< std::unique_ptr< BaseOutputModule< TypeTag > > > outputModules_
Definition: fvbasediscretization.hh:2021
ElementMapper elementMapper_
Definition: fvbasediscretization.hh:1993
NewtonMethod newtonMethod_
Definition: fvbasediscretization.hh:1999
std::size_t numTotalDof() const
Returns the total number of degrees of freedom (i.e., grid plux auxiliary DOFs)
Definition: fvbasediscretization.hh:1595
void applyInitialSolution()
Applies the initial solution for all degrees of freedom to which the model applies.
Definition: fvbasediscretization.hh:529
Implementation & asImp_()
Definition: fvbasediscretization.hh:1979
void updateCachedIntensiveQuantities(const IntensiveQuantities &intQuants, unsigned globalIdx, unsigned timeIdx) const
Update the intensive quantity cache for a entity on the grid at given time.
Definition: fvbasediscretization.hh:674
std::string primaryVarName(unsigned pvIdx) const
Given an primary variable index, return a human readable name.
Definition: fvbasediscretization.hh:1638
void invalidateIntensiveQuantitiesCache(unsigned timeIdx) const
Invalidate the whole intensive quantity cache for time index.
Definition: fvbasediscretization.hh:716
Linearizer & linearizer()
Returns the object which linearizes the global system of equations at the current solution.
Definition: fvbasediscretization.hh:1253
const BaseAuxiliaryModule< TypeTag > * auxiliaryModule(unsigned auxEqModIdx) const
Returns a given module for auxiliary equations.
Definition: fvbasediscretization.hh:1881
std::vector< std::vector< unsigned char > > intensiveQuantityCacheUpToDate_
Definition: fvbasediscretization.hh:2017
void globalStorage(EqVector &storage, unsigned timeIdx=0) const
Compute the integral over the domain of the storage terms of all conservation quantities.
Definition: fvbasediscretization.hh:1022
GridView gridView_
Definition: fvbasediscretization.hh:1990
Scalar dofTotalVolume(unsigned globalIdx) const
Returns the volume of a given control volume.
Definition: fvbasediscretization.hh:1199
static void registerParameters()
Register all run-time parameters for the model.
Definition: fvbasediscretization.hh:426
const SolutionVector & solution(unsigned timeIdx) const
Reference to the solution at a given history index as a block vector.
Definition: fvbasediscretization.hh:1225
bool verbose_() const
Returns whether messages should be printed.
Definition: fvbasediscretization.hh:1976
void shiftStorageCache(unsigned numSlots=1) const
Shift storage cache by a given number of time step slots.
Definition: fvbasediscretization.hh:927
Simulator & simulator_
Definition: fvbasediscretization.hh:1987
const LocalResidual & localResidual(unsigned openMpThreadId) const
Returns the object to calculate the local residual function.
Definition: fvbasediscretization.hh:1276
std::size_t numGridDof() const
Returns the number of degrees of freedom (DOFs) for the computational grid.
Definition: fvbasediscretization.hh:1578
Scalar gridTotalVolume_
Definition: fvbasediscretization.hh:2023
const DofMapper & dofMapper() const
Mapper to convert the Dune entities of the discretization's degrees of freedoms are to indices.
Definition: fvbasediscretization.hh:1602
bool storeIntensiveQuantities() const
Returns true if the cache for intensive quantities is enabled.
Definition: fvbasediscretization.hh:1887
std::vector< LocalLinearizer > localLinearizer_
Definition: fvbasediscretization.hh:2007
void invalidateStorageCache(unsigned timeIdx) const
Invalidate the whole storage cache for a given time index.
Definition: fvbasediscretization.hh:909
void serialize(Restarter &)
Serializes the current state of the model.
Definition: fvbasediscretization.hh:1507
bool enableThermodynamicHints_
Definition: fvbasediscretization.hh:2035
void invalidateStorageCacheEntry(unsigned globalIdx, unsigned timeIdx) const
Invalidate the storage cache for a given DOF and time index.
Definition: fvbasediscretization.hh:897
VertexMapper vertexMapper_
Definition: fvbasediscretization.hh:1994
void resetLinearizer()
Resets the Jacobian matrix linearizer, so that the boundary types can be altered.
Definition: fvbasediscretization.hh:1621
bool enableStorageCache() const
Returns true iff the storage term is cached.
Definition: fvbasediscretization.hh:818
size_t numDof() const
Definition: fvbasediscretization.hh:1210
const GridView & gridView() const
Reference to the grid view of the spatial domain.
Definition: fvbasediscretization.hh:1821
void addOutputModule(std::unique_ptr< BaseOutputModule< TypeTag > > newModule)
Add an module for writing visualization output after a timestep.
Definition: fvbasediscretization.hh:1669
const IntensiveQuantities * cachedIntensiveQuantities(unsigned globalIdx, unsigned timeIdx) const
Return the cached intensive quantities for a entity on the grid at given time.
Definition: fvbasediscretization.hh:643
This class stores an array of IntensiveQuantities objects, one intensive quantities object for each o...
Definition: fvbaseelementcontext.hh:55
Provide the properties at a face which make sense independently of the conserved quantities.
Definition: fvbaseextensivequantities.hh:48
This class calculates gradients of arbitrary quantities at flux integration points using the two-poin...
Definition: fvbasegradientcalculator.hh:52
Base class for the model specific class which provides access to all intensive (i....
Definition: fvbaseintensivequantities.hh:45
The common code for the linearizers of non-linear systems of equations.
Definition: fvbaselinearizer.hh:78
Element-wise caculation of the residual matrix for models based on a finite volume spatial discretiza...
Definition: fvbaselocalresidual.hh:63
Represents the primary variables used by the a model.
Definition: fvbaseprimaryvariables.hh:54
This is a grid manager which does not create any border list.
Definition: nullborderlistmanager.hh:44
static void registerParameters()
Register all run-time parameters for the Newton method.
Definition: newtonmethod.hh:135
Manages the initializing and running of time dependent problems.
Definition: simulator.hh:84
Simplifies multi-threaded capabilities.
Definition: threadmanager.hpp:36
static unsigned maxThreads()
Return the maximum number of threads of the current process.
Definition: threadmanager.hpp:66
static unsigned threadId()
Return the index of the current OpenMP thread.
Provides an STL-iterator like interface to iterate over the enties of a GridView in OpenMP threaded a...
Definition: threadedentityiterator.hh:42
bool isFinished(const EntityIterator &it) const
Definition: threadedentityiterator.hh:67
EntityIterator increment()
Definition: threadedentityiterator.hh:80
EntityIterator beginParallel()
Definition: threadedentityiterator.hh:54
A simple class which makes sure that a timer gets stopped if an exception is thrown.
Definition: timerguard.hh:42
Provides an encapsulation to measure the system time.
Definition: timer.hpp:46
void start()
Start counting the time resources used by the simulation.
void halt()
Stop the measurement reset all timing values.
double stop()
Stop counting the time resources.
Simplifies writing multi-file VTK datasets.
Definition: vtkmultiwriter.hh:65
ScalarBuffer * allocateManagedScalarBuffer(std::size_t numEntities)
Allocate a managed buffer for a scalar field.
Definition: vtkmultiwriter.hh:192
VTK output module for the fluid composition.
Definition: vtkprimaryvarsmodule.hpp:48
static void registerParameters()
Register all run-time parameters for the Vtk output module.
Definition: vtkprimaryvarsmodule.hpp:74
Definition: alignedallocator.hh:97
Declare the properties used by the infrastructure code of the finite volume discretizations.
Provides data handles for parallel communication which operate on DOFs.
Declares the parameters for the black oil model.
Definition: fvbaseprimaryvariables.hh:161
auto Get(bool errorIfNotRegistered=true)
Retrieve a runtime parameter.
Definition: parametersystem.hpp:187
Definition: blackoilmodel.hh:75
Definition: blackoilbioeffectsmodules.hh:45
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(....
Definition: propertysystem.hh:233
std::string to_string(const ConvergenceReport::ReservoirFailure::Type t)
Definition: fvbasediscretization.hh:2057
static void serializeOp(Serializer &serializer, SolutionType &solution)
Definition: fvbasediscretization.hh:2059
Definition: fvbasediscretization.hh:272
GetPropType< TypeTag, Properties::GridView > GridView
Definition: fvbasediscretization.hh:113
GetPropType< TypeTag, Properties::DofMapper > DofMapper
Definition: fvbasediscretization.hh:112
The class which marks the border indices associated with the degrees of freedom on a process boundary...
Definition: basicproperties.hh:129
The secondary variables of a boundary segment.
Definition: fvbaseproperties.hh:158
GetPropType< TypeTag, Properties::RateVector > type
Definition: fvbasediscretization.hh:160
Type of object for specifying boundary conditions.
Definition: fvbaseproperties.hh:125
The secondary variables of a constraint degree of freedom.
Definition: fvbaseproperties.hh:161
The class which represents a constraint degree of freedom.
Definition: fvbaseproperties.hh:128
The part of the extensive quantities which is specific to the spatial discretization.
Definition: fvbaseproperties.hh:175
Definition: fvbaseproperties.hh:151
The discretization specific part of the local residual.
Definition: fvbaseproperties.hh:97
typename BaseDiscretization::BlockVectorWrapper type
Definition: fvbasediscretization.hh:283
Definition: fvbaseproperties.hh:83
The secondary variables of all degrees of freedom in an element's stencil.
Definition: fvbaseproperties.hh:155
Dune::BlockVector< GetPropType< TypeTag, Properties::EqVector > > type
Definition: fvbasediscretization.hh:174
A vector of holding a quantity for each equation for each DOF of an element.
Definition: fvbaseproperties.hh:118
Dune::MultipleCodimMultipleGeomTypeMapper< GetPropType< TypeTag, Properties::GridView > > type
Definition: fvbasediscretization.hh:106
The mapper to find the global index of an element.
Definition: fvbaseproperties.hh:228
Specify whether the some degrees of fredom can be constraint.
Definition: fvbaseproperties.hh:214
Specify if experimental features should be enabled or not.
Definition: fvbaseproperties.hh:256
Dune::FieldVector< GetPropType< TypeTag, Properties::Scalar >, getPropValue< TypeTag, Properties::NumEq >()> type
Definition: fvbasediscretization.hh:143
A vector of holding a quantity for each equation (usually at a given spatial location)
Definition: fvbaseproperties.hh:115
Specify whether the storage terms use extensive quantities or not.
Definition: fvbaseproperties.hh:248
Dune::BlockVector< GetPropType< TypeTag, Properties::EqVector > > type
Definition: fvbasediscretization.hh:181
Vector containing a quantity of for equation for each DOF of the whole grid.
Definition: linalgproperties.hh:54
Calculates gradients of arbitrary quantities at flux integration points.
Definition: fvbaseproperties.hh:167
The secondary variables within a sub-control volume.
Definition: fvbaseproperties.hh:139
The class which linearizes the non-linear system of equations.
Definition: newtonmethodproperties.hh:36
A vector of primary variables within a sub-control volume.
Definition: fvbaseproperties.hh:136
GetPropType< TypeTag, Properties::EqVector > type
Definition: fvbasediscretization.hh:153
Vector containing volumetric or areal rates of quantities.
Definition: fvbaseproperties.hh:122
Manages the simulation time.
Definition: basicproperties.hh:120
Dune::BlockVector< GetPropType< TypeTag, Properties::PrimaryVariables > > type
Definition: fvbasediscretization.hh:195
Vector containing all primary variables of the grid.
Definition: fvbaseproperties.hh:132
The OpenMP threads manager.
Definition: fvbaseproperties.hh:189
The history size required by the time discretization.
Definition: fvbaseproperties.hh:240
a tag to mark properties as undefined
Definition: propertysystem.hh:38
Definition: fvbaseproperties.hh:196
Specify whether to use volumetric residuals or not.
Definition: fvbaseproperties.hh:252
Dune::MultipleCodimMultipleGeomTypeMapper< GetPropType< TypeTag, Properties::GridView > > type
Definition: fvbasediscretization.hh:101
The mapper to find the global index of a vertex.
Definition: fvbaseproperties.hh:222
Specify the format the VTK output is written to disk.
Definition: fvbaseproperties.hh:210