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/version.hh>
32#include <dune/common/fvector.hh>
33#include <dune/common/fmatrix.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 <cstddef>
71#include <limits>
72#include <list>
73#include <stdexcept>
74#include <sstream>
75#include <string>
76#include <type_traits>
77#include <vector>
78
79namespace Opm {
80template<class TypeTag>
81class FvBaseDiscretizationNoAdapt;
82template<class TypeTag>
83class FvBaseDiscretization;
84
85} // namespace Opm
86
87namespace Opm::Properties {
88
90template<class TypeTag>
91struct Simulator<TypeTag, TTag::FvBaseDiscretization>
93
95template<class TypeTag>
96struct VertexMapper<TypeTag, TTag::FvBaseDiscretization>
97{ using type = Dune::MultipleCodimMultipleGeomTypeMapper<GetPropType<TypeTag, Properties::GridView>>; };
98
100template<class TypeTag>
102{ using type = Dune::MultipleCodimMultipleGeomTypeMapper<GetPropType<TypeTag, Properties::GridView>>; };
103
105template<class TypeTag>
107{
110
111public:
113};
114
115template<class TypeTag>
118
119template<class TypeTag>
122
123template<class TypeTag>
126
128template<class TypeTag>
131
135template<class TypeTag>
136struct EqVector<TypeTag, TTag::FvBaseDiscretization>
137{
138 using type = Dune::FieldVector<GetPropType<TypeTag, Properties::Scalar>,
139 getPropValue<TypeTag, Properties::NumEq>()>;
140};
141
147template<class TypeTag>
148struct RateVector<TypeTag, TTag::FvBaseDiscretization>
150
154template<class TypeTag>
157
161template<class TypeTag>
162struct Constraints<TypeTag, TTag::FvBaseDiscretization>
164
168template<class TypeTag>
170{ using type = Dune::BlockVector<GetPropType<TypeTag, Properties::EqVector>>; };
171
175template<class TypeTag>
177{ using type = Dune::BlockVector<GetPropType<TypeTag, Properties::EqVector>>; };
178
182template<class TypeTag>
185
189template<class TypeTag>
191{ using type = Dune::BlockVector<GetPropType<TypeTag, Properties::PrimaryVariables>>; };
192
198template<class TypeTag>
201
205template<class TypeTag>
208
209template<class TypeTag>
212
213template<class TypeTag>
216
220template<class TypeTag>
223
224template<class TypeTag>
226{ static constexpr bool value = true; };
227
231template<class TypeTag>
232struct Linearizer<TypeTag, TTag::FvBaseDiscretization>
234
236template<class TypeTag>
238{ static constexpr int value = Dune::VTK::ascii; };
239
240// disable constraints by default
241template<class TypeTag>
243{ static constexpr bool value = false; };
244
246template<class TypeTag>
248{ static constexpr int value = 2; };
249
252template<class TypeTag>
254{ static constexpr bool value = false; };
255
256// use volumetric residuals is default
257template<class TypeTag>
259{ static constexpr bool value = true; };
260
263template<class TypeTag>
265{ static constexpr bool value = true; };
266
267template <class TypeTag, class MyTypeTag>
269
270#if !HAVE_DUNE_FEM
271template<class TypeTag>
274
275template<class TypeTag>
277{
280};
281#endif
282
283} // namespace Opm::Properties
284
285namespace Opm {
286
292template<class TypeTag>
294{
295 using Implementation = GetPropType<TypeTag, Properties::Model>;
322
325
326 enum {
327 numEq = getPropValue<TypeTag, Properties::NumEq>(),
328 historySize = getPropValue<TypeTag, Properties::TimeDiscHistorySize>(),
329 };
330
331 using IntensiveQuantitiesVector = std::vector<IntensiveQuantities, aligned_allocator<IntensiveQuantities, alignof(IntensiveQuantities)> >;
332
333 using Element = typename GridView::template Codim<0>::Entity;
334 using ElementIterator = typename GridView::template Codim<0>::Iterator;
335
336 using Toolbox = MathToolbox<Evaluation>;
337 using VectorBlock = Dune::FieldVector<Evaluation, numEq>;
338 using EvalEqVector = Dune::FieldVector<Evaluation, numEq>;
339
340 using LocalEvalBlockVector = typename LocalResidual::LocalEvalBlockVector;
341
342public:
344 {
345 protected:
346 SolutionVector blockVector_;
347 public:
348 BlockVectorWrapper(const std::string&, const size_t size)
349 : blockVector_(size)
350 {}
351
353
355 {
356 BlockVectorWrapper result("dummy", 3);
357 result.blockVector_[0] = 1.0;
358 result.blockVector_[1] = 2.0;
359 result.blockVector_[2] = 3.0;
360
361 return result;
362 }
363
364 SolutionVector& blockVector()
365 { return blockVector_; }
366 const SolutionVector& blockVector() const
367 { return blockVector_; }
368
369 bool operator==(const BlockVectorWrapper& wrapper) const
370 {
371 return std::equal(this->blockVector_.begin(), this->blockVector_.end(),
372 wrapper.blockVector_.begin(), wrapper.blockVector_.end());
373 }
374
375 template<class Serializer>
376 void serializeOp(Serializer& serializer)
377 {
378 serializer(blockVector_);
379 }
380 };
381
382private:
385
386 // copying a discretization object is not a good idea
388
389public:
390 // this constructor required to be explicitly specified because
391 // we've defined a constructor above which deletes all implicitly
392 // generated constructors in C++.
393 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_(new 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 {
406 bool isEcfv = std::is_same<Discretization, EcfvDiscretization<TypeTag> >::value;
407 if (enableGridAdaptation_ && !isEcfv)
408 throw std::invalid_argument("Grid adaptation currently only works for the "
409 "element-centered finite volume discretization (is: "
410 +Dune::className<Discretization>()+")");
411
412 PrimaryVariables::init();
413 size_t numDof = asImp_().numGridDof();
414 for (unsigned timeIdx = 0; timeIdx < historySize; ++timeIdx) {
416 intensiveQuantityCache_[timeIdx].resize(numDof);
417 intensiveQuantityCacheUpToDate_[timeIdx].resize(numDof, /*value=*/false);
418 }
419
421 storageCache_[timeIdx].resize(numDof);
422 }
423
425 asImp_().registerOutputModules_();
426 }
427
429 {
430 // delete all output modules
431 auto modIt = outputModules_.begin();
432 const auto& modEndIt = outputModules_.end();
433 for (; modIt != modEndIt; ++modIt)
434 delete *modIt;
435
436 delete linearizer_;
437 }
438
442 static void registerParameters()
443 {
444 Linearizer::registerParameters();
445 LocalLinearizer::registerParameters();
446 LocalResidual::registerParameters();
447 GradientCalculator::registerParameters();
448 IntensiveQuantities::registerParameters();
449 ExtensiveQuantities::registerParameters();
451 Linearizer::registerParameters();
452 PrimaryVariables::registerParameters();
453 // register runtime parameters of the output modules
455
456 Parameters::Register<Parameters::EnableGridAdaptation>
457 ("Enable adaptive grid refinement/coarsening");
458 Parameters::Register<Parameters::EnableVtkOutput>
459 ("Global switch for turning on writing VTK files");
460 Parameters::Register<Parameters::EnableThermodynamicHints>
461 ("Enable thermodynamic hints");
462 Parameters::Register<Parameters::EnableIntensiveQuantityCache>
463 ("Turn on caching of intensive quantities");
464 Parameters::Register<Parameters::EnableStorageCache>
465 ("Store previous storage terms and avoid re-calculating them.");
466 Parameters::Register<Parameters::OutputDir>
467 ("The directory to which result files are written");
468 }
469
474 {
475 // initialize the volume of the finite volumes to zero
476 size_t numDof = asImp_().numGridDof();
477 dofTotalVolume_.resize(numDof);
478 std::fill(dofTotalVolume_.begin(), dofTotalVolume_.end(), 0.0);
479
480 ElementContext elemCtx(simulator_);
481 gridTotalVolume_ = 0.0;
482
483 // iterate through the grid and evaluate the initial condition
484 for (const auto& elem : elements(gridView_)) {
485 const bool isInteriorElement = elem.partitionType() == Dune::InteriorEntity;
486 // ignore everything which is not in the interior if the
487 // current process' piece of the grid
488 if (!isInteriorElement)
489 continue;
490
491 // deal with the current element
492 elemCtx.updateStencil(elem);
493 const auto& stencil = elemCtx.stencil(/*timeIdx=*/0);
494
495 // loop over all element vertices, i.e. sub control volumes
496 for (unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(/*timeIdx=*/0); dofIdx++) {
497 // map the local degree of freedom index to the global one
498 unsigned globalIdx = elemCtx.globalSpaceIndex(dofIdx, /*timeIdx=*/0);
499
500 Scalar dofVolume = stencil.subControlVolume(dofIdx).volume();
501 dofTotalVolume_[globalIdx] += dofVolume;
502 if (isInteriorElement)
503 gridTotalVolume_ += dofVolume;
504 }
505 }
506
507 // determine which DOFs should be considered to lie fully in the interior of the
508 // local process grid partition: those which do not have a non-zero volume
509 // before taking the peer processes into account...
510 isLocalDof_.resize(numDof);
511 for (unsigned dofIdx = 0; dofIdx < numDof; ++dofIdx)
512 isLocalDof_[dofIdx] = (dofTotalVolume_[dofIdx] != 0.0);
513
514 // add the volumes of the DOFs on the process boundaries
515 const auto sumHandle =
516 GridCommHandleFactory::template sumHandle<Scalar>(dofTotalVolume_,
517 asImp_().dofMapper());
518 gridView_.communicate(*sumHandle,
519 Dune::InteriorBorder_All_Interface,
520 Dune::ForwardCommunication);
521
522 // sum up the volumes of the grid partitions
524
525 linearizer_->init(simulator_);
526 for (unsigned threadId = 0; threadId < ThreadManager::maxThreads(); ++threadId)
527 localLinearizer_[threadId].init(simulator_);
528
531 // invalidate all cached intensive quantities
532 for (unsigned timeIdx = 0; timeIdx < historySize; ++ timeIdx)
534 }
535
536 newtonMethod_.finishInit();
537 }
538
543 { return enableGridAdaptation_; }
544
550 {
551 // first set the whole domain to zero
552 SolutionVector& uCur = asImp_().solution(/*timeIdx=*/0);
553 uCur = Scalar(0.0);
554
555 ElementContext elemCtx(simulator_);
556
557 // iterate through the grid and evaluate the initial condition
558 for (const auto& elem : elements(gridView_)) {
559 // ignore everything which is not in the interior if the
560 // current process' piece of the grid
561 if (elem.partitionType() != Dune::InteriorEntity)
562 continue;
563
564 // deal with the current element
565 elemCtx.updateStencil(elem);
566
567 // loop over all element vertices, i.e. sub control volumes
568 for (unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(/*timeIdx=*/0); dofIdx++)
569 {
570 // map the local degree of freedom index to the global one
571 unsigned globalIdx = elemCtx.globalSpaceIndex(dofIdx, /*timeIdx=*/0);
572
573 // let the problem do the dirty work of nailing down
574 // the initial solution.
575 simulator_.problem().initial(uCur[globalIdx], elemCtx, dofIdx, /*timeIdx=*/0);
576 asImp_().supplementInitialSolution_(uCur[globalIdx], elemCtx, dofIdx, /*timeIdx=*/0);
577 uCur[globalIdx].checkDefined();
578 }
579 }
580
581 // synchronize the ghost DOFs (if necessary)
582 asImp_().syncOverlap();
583
584 // also set the solutions of the "previous" time steps to the initial solution.
585 for (unsigned timeIdx = 1; timeIdx < historySize; ++timeIdx)
586 solution(timeIdx) = solution(/*timeIdx=*/0);
587
588 simulator_.problem().initialSolutionApplied();
589
590#ifndef NDEBUG
591 for (unsigned timeIdx = 0; timeIdx < historySize; ++timeIdx) {
592 const auto& sol = solution(timeIdx);
593 for (unsigned dofIdx = 0; dofIdx < sol.size(); ++dofIdx)
594 sol[dofIdx].checkDefined();
595 }
596#endif // NDEBUG
597 }
598
603 void prefetch(const Element&) const
604 {
605 // do nothing by default
606 }
607
611 NewtonMethod& newtonMethod()
612 { return newtonMethod_; }
613
617 const NewtonMethod& newtonMethod() const
618 { return newtonMethod_; }
619
635 const IntensiveQuantities* thermodynamicHint(unsigned globalIdx, unsigned timeIdx) const
636 {
638 return 0;
639
640 // the intensive quantities cache doubles as thermodynamic hint
641 return cachedIntensiveQuantities(globalIdx, timeIdx);
642 }
643
655 const IntensiveQuantities* cachedIntensiveQuantities(unsigned globalIdx, unsigned timeIdx) const
656 {
658 return nullptr;
659 }
660
661 // With the storage cache enabled, usually only the
662 // intensive quantities for the most recent time step are
663 // cached. However, this may be false for some Problem
664 // variants, so we should check if the cache exists for
665 // the timeIdx in question.
666 if (timeIdx > 0 && enableStorageCache_ && intensiveQuantityCache_[timeIdx].empty()) {
667 return nullptr;
668 }
669
670 return &intensiveQuantityCache_[timeIdx][globalIdx];
671 }
672
681 void updateCachedIntensiveQuantities(const IntensiveQuantities& intQuants,
682 unsigned globalIdx,
683 unsigned timeIdx) const
684 {
686 return;
687
688 intensiveQuantityCache_[timeIdx][globalIdx] = intQuants;
689 intensiveQuantityCacheUpToDate_[timeIdx][globalIdx] = 1;
690 }
691
700 unsigned timeIdx,
701 bool newValue) const
702 {
704 return;
705
706 intensiveQuantityCacheUpToDate_[timeIdx][globalIdx] = newValue ? 1 : 0;
707 }
708
714 void invalidateIntensiveQuantitiesCache(unsigned timeIdx) const
715 {
717 std::fill(intensiveQuantityCacheUpToDate_[timeIdx].begin(),
718 intensiveQuantityCacheUpToDate_[timeIdx].end(),
719 /*value=*/0);
720 }
721 }
722
723 void invalidateAndUpdateIntensiveQuantities(unsigned timeIdx) const
724 {
726
727 // loop over all elements...
728 ThreadedEntityIterator<GridView, /*codim=*/0> threadedElemIt(gridView_);
729#ifdef _OPENMP
730#pragma omp parallel
731#endif
732 {
733 ElementContext elemCtx(simulator_);
734 ElementIterator elemIt = threadedElemIt.beginParallel();
735 for (; !threadedElemIt.isFinished(elemIt); elemIt = threadedElemIt.increment()) {
736 const Element& elem = *elemIt;
737 elemCtx.updatePrimaryStencil(elem);
738 elemCtx.updatePrimaryIntensiveQuantities(timeIdx);
739 }
740 }
741 }
742
743 template <class GridViewType>
744 void invalidateAndUpdateIntensiveQuantities(unsigned timeIdx, const GridViewType& gridView) const
745 {
746 // loop over all elements...
747 ThreadedEntityIterator<GridViewType, /*codim=*/0> threadedElemIt(gridView);
748#ifdef _OPENMP
749#pragma omp parallel
750#endif
751 {
752
753 ElementContext elemCtx(simulator_);
754 auto elemIt = threadedElemIt.beginParallel();
755 for (; !threadedElemIt.isFinished(elemIt); elemIt = threadedElemIt.increment()) {
756 if (elemIt->partitionType() != Dune::InteriorEntity) {
757 continue;
758 }
759 const Element& elem = *elemIt;
760 elemCtx.updatePrimaryStencil(elem);
761 // Mark cache for this element as invalid.
762 const std::size_t numPrimaryDof = elemCtx.numPrimaryDof(timeIdx);
763 for (unsigned dofIdx = 0; dofIdx < numPrimaryDof; ++dofIdx) {
764 const unsigned globalIndex = elemCtx.globalSpaceIndex(dofIdx, timeIdx);
765 setIntensiveQuantitiesCacheEntryValidity(globalIndex, timeIdx, false);
766 }
767 // Update for this element.
768 elemCtx.updatePrimaryIntensiveQuantities(/*timeIdx=*/0);
769 }
770 }
771 }
772
781 void shiftIntensiveQuantityCache(unsigned numSlots = 1)
782 {
784 return;
785
786 if (enableStorageCache() && simulator_.problem().recycleFirstIterationStorage()) {
787 // If the storage term is cached, the intensive quantities of the previous
788 // time steps do not need to be accessed, and we can thus spare ourselves to
789 // copy the objects for the intensive quantities.
790 // However, if the storage term at the start of the timestep cannot be deduced
791 // from the primary variables, we must calculate it from the old intensive
792 // quantities, and need to shift them.
793 return;
794 }
795
796 assert(numSlots > 0);
797
798 for (unsigned timeIdx = 0; timeIdx < historySize - numSlots; ++ timeIdx) {
799 intensiveQuantityCache_[timeIdx + numSlots] = intensiveQuantityCache_[timeIdx];
801 }
802
803 // the cache for the most recent time indices do not need to be invalidated
804 // because the solution for them did not change (TODO: that assumes that there is
805 // no post-processing of the solution after a time step! fix it?)
806 }
807
815 { return enableStorageCache_; }
816
825
836 const EqVector& cachedStorage(unsigned globalIdx, unsigned timeIdx) const
837 {
838 assert(enableStorageCache_);
839 return storageCache_[timeIdx][globalIdx];
840 }
841
853 void updateCachedStorage(unsigned globalIdx, unsigned timeIdx, const EqVector& value) const
854 {
855 assert(enableStorageCache_);
856 storageCache_[timeIdx][globalIdx] = value;
857 }
858
866 Scalar globalResidual(GlobalEqVector& dest,
867 const SolutionVector& u) const
868 {
869 SolutionVector tmp(asImp_().solution(/*timeIdx=*/0));
870 mutableSolution(/*timeIdx=*/0) = u;
871 Scalar res = asImp_().globalResidual(dest);
872 mutableSolution(/*timeIdx=*/0) = tmp;
873 return res;
874 }
875
882 Scalar globalResidual(GlobalEqVector& dest) const
883 {
884 dest = 0;
885
886 std::mutex mutex;
887 ThreadedEntityIterator<GridView, /*codim=*/0> threadedElemIt(gridView_);
888#ifdef _OPENMP
889#pragma omp parallel
890#endif
891 {
892 // Attention: the variables below are thread specific and thus cannot be
893 // moved in front of the #pragma!
894 unsigned threadId = ThreadManager::threadId();
895 ElementContext elemCtx(simulator_);
896 ElementIterator elemIt = threadedElemIt.beginParallel();
897 LocalEvalBlockVector residual, storageTerm;
898
899 for (; !threadedElemIt.isFinished(elemIt); elemIt = threadedElemIt.increment()) {
900 const Element& elem = *elemIt;
901 if (elem.partitionType() != Dune::InteriorEntity)
902 continue;
903
904 elemCtx.updateAll(elem);
905 residual.resize(elemCtx.numDof(/*timeIdx=*/0));
906 storageTerm.resize(elemCtx.numPrimaryDof(/*timeIdx=*/0));
907 asImp_().localResidual(threadId).eval(residual, elemCtx);
908
909 size_t numPrimaryDof = elemCtx.numPrimaryDof(/*timeIdx=*/0);
910 mutex.lock();
911 for (unsigned dofIdx = 0; dofIdx < numPrimaryDof; ++dofIdx) {
912 unsigned globalI = elemCtx.globalSpaceIndex(dofIdx, /*timeIdx=*/0);
913 for (unsigned eqIdx = 0; eqIdx < numEq; ++ eqIdx)
914 dest[globalI][eqIdx] += Toolbox::value(residual[dofIdx][eqIdx]);
915 }
916 mutex.unlock();
917 }
918 }
919
920 // add up the residuals on the process borders
921 const auto sumHandle =
922 GridCommHandleFactory::template sumHandle<EqVector>(dest, asImp_().dofMapper());
923 gridView_.communicate(*sumHandle,
924 Dune::InteriorBorder_InteriorBorder_Interface,
925 Dune::ForwardCommunication);
926
927 // calculate the square norm of the residual. this is not
928 // entirely correct, since the residual for the finite volumes
929 // which are on the boundary are counted once for every
930 // process. As often in life: shit happens (, we don't care)...
931 Scalar result2 = dest.two_norm2();
932 result2 = asImp_().gridView().comm().sum(result2);
933
934 return std::sqrt(result2);
935 }
936
943 void globalStorage(EqVector& storage, unsigned timeIdx = 0) const
944 {
945 storage = 0;
946
947 std::mutex mutex;
948 ThreadedEntityIterator<GridView, /*codim=*/0> threadedElemIt(gridView());
949#ifdef _OPENMP
950#pragma omp parallel
951#endif
952 {
953 // Attention: the variables below are thread specific and thus cannot be
954 // moved in front of the #pragma!
955 unsigned threadId = ThreadManager::threadId();
956 ElementContext elemCtx(simulator_);
957 ElementIterator elemIt = threadedElemIt.beginParallel();
958 LocalEvalBlockVector elemStorage;
959
960 // in this method, we need to disable the storage cache because we want to
961 // evaluate the storage term for other time indices than the most recent one
962 elemCtx.setEnableStorageCache(false);
963
964 for (; !threadedElemIt.isFinished(elemIt); elemIt = threadedElemIt.increment()) {
965 const Element& elem = *elemIt;
966 if (elem.partitionType() != Dune::InteriorEntity)
967 continue; // ignore ghost and overlap elements
968
969 elemCtx.updateStencil(elem);
970 elemCtx.updatePrimaryIntensiveQuantities(timeIdx);
971
972 size_t numPrimaryDof = elemCtx.numPrimaryDof(timeIdx);
973 elemStorage.resize(numPrimaryDof);
974
975 localResidual(threadId).evalStorage(elemStorage, elemCtx, timeIdx);
976
977 mutex.lock();
978 for (unsigned dofIdx = 0; dofIdx < numPrimaryDof; ++dofIdx)
979 for (unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx)
980 storage[eqIdx] += Toolbox::value(elemStorage[dofIdx][eqIdx]);
981 mutex.unlock();
982 }
983 }
984
985 storage = gridView_.comm().sum(storage);
986 }
987
995 void checkConservativeness([[maybe_unused]] Scalar tolerance = -1,
996 [[maybe_unused]] bool verbose=false) const
997 {
998#ifndef NDEBUG
999 Scalar totalBoundaryArea(0.0);
1000 Scalar totalVolume(0.0);
1001 EvalEqVector totalRate(0.0);
1002
1003 // take the newton tolerance times the total volume of the grid if we're not
1004 // given an explicit tolerance...
1005 if (tolerance <= 0) {
1006 tolerance =
1007 simulator_.model().newtonMethod().tolerance()
1008 * simulator_.model().gridTotalVolume()
1009 * 1000;
1010 }
1011
1012 // we assume the implicit Euler time discretization for now...
1013 assert(historySize == 2);
1014
1015 EqVector storageBeginTimeStep(0.0);
1016 globalStorage(storageBeginTimeStep, /*timeIdx=*/1);
1017
1018 EqVector storageEndTimeStep(0.0);
1019 globalStorage(storageEndTimeStep, /*timeIdx=*/0);
1020
1021 // calculate the rate at the boundary and the source rate
1022 ElementContext elemCtx(simulator_);
1023 elemCtx.setEnableStorageCache(false);
1024 auto eIt = simulator_.gridView().template begin</*codim=*/0>();
1025 const auto& elemEndIt = simulator_.gridView().template end</*codim=*/0>();
1026 for (; eIt != elemEndIt; ++eIt) {
1027 if (eIt->partitionType() != Dune::InteriorEntity)
1028 continue; // ignore ghost and overlap elements
1029
1030 elemCtx.updateAll(*eIt);
1031
1032 // handle the boundary terms
1033 if (elemCtx.onBoundary()) {
1034 BoundaryContext boundaryCtx(elemCtx);
1035
1036 for (unsigned faceIdx = 0; faceIdx < boundaryCtx.numBoundaryFaces(/*timeIdx=*/0); ++faceIdx) {
1037 BoundaryRateVector values;
1038 simulator_.problem().boundary(values,
1039 boundaryCtx,
1040 faceIdx,
1041 /*timeIdx=*/0);
1042 Valgrind::CheckDefined(values);
1043
1044 unsigned dofIdx = boundaryCtx.interiorScvIndex(faceIdx, /*timeIdx=*/0);
1045 const auto& insideIntQuants = elemCtx.intensiveQuantities(dofIdx, /*timeIdx=*/0);
1046
1047 Scalar bfArea =
1048 boundaryCtx.boundarySegmentArea(faceIdx, /*timeIdx=*/0)
1049 * insideIntQuants.extrusionFactor();
1050
1051 for (unsigned i = 0; i < values.size(); ++i)
1052 values[i] *= bfArea;
1053
1054 totalBoundaryArea += bfArea;
1055 for (unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx)
1056 totalRate[eqIdx] += values[eqIdx];
1057 }
1058 }
1059
1060 // deal with the source terms
1061 for (unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(/*timeIdx=*/0); ++ dofIdx) {
1062 RateVector values;
1063 simulator_.problem().source(values,
1064 elemCtx,
1065 dofIdx,
1066 /*timeIdx=*/0);
1067 Valgrind::CheckDefined(values);
1068
1069 const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, /*timeIdx=*/0);
1070 Scalar dofVolume =
1071 elemCtx.dofVolume(dofIdx, /*timeIdx=*/0)
1072 * intQuants.extrusionFactor();
1073 for (unsigned eqIdx = 0; eqIdx < numEq; ++ eqIdx)
1074 totalRate[eqIdx] += -dofVolume*Toolbox::value(values[eqIdx]);
1075 totalVolume += dofVolume;
1076 }
1077 }
1078
1079 // summarize everything over all processes
1080 const auto& comm = simulator_.gridView().comm();
1081 totalRate = comm.sum(totalRate);
1082 totalBoundaryArea = comm.sum(totalBoundaryArea);
1083 totalVolume = comm.sum(totalVolume);
1084
1085 if (comm.rank() == 0) {
1086 EqVector storageRate = storageBeginTimeStep;
1087 storageRate -= storageEndTimeStep;
1088 storageRate /= simulator_.timeStepSize();
1089 if (verbose) {
1090 std::cout << "storage at beginning of time step: " << storageBeginTimeStep << "\n";
1091 std::cout << "storage at end of time step: " << storageEndTimeStep << "\n";
1092 std::cout << "rate based on storage terms: " << storageRate << "\n";
1093 std::cout << "rate based on source and boundary terms: " << totalRate << "\n";
1094 std::cout << "difference in rates: ";
1095 for (unsigned eqIdx = 0; eqIdx < EqVector::dimension; ++eqIdx)
1096 std::cout << (storageRate[eqIdx] - Toolbox::value(totalRate[eqIdx])) << " ";
1097 std::cout << "\n";
1098 }
1099 for (unsigned eqIdx = 0; eqIdx < EqVector::dimension; ++eqIdx) {
1100 Scalar eps =
1101 (std::abs(storageRate[eqIdx]) + Toolbox::value(totalRate[eqIdx]))*tolerance;
1102 eps = std::max(tolerance, eps);
1103 assert(std::abs(storageRate[eqIdx] - Toolbox::value(totalRate[eqIdx])) <= eps);
1104 }
1105 }
1106#endif // NDEBUG
1107 }
1108
1114 Scalar dofTotalVolume(unsigned globalIdx) const
1115 { return dofTotalVolume_[globalIdx]; }
1116
1122 bool isLocalDof(unsigned globalIdx) const
1123 { return isLocalDof_[globalIdx]; }
1124
1129 Scalar gridTotalVolume() const
1130 { return gridTotalVolume_; }
1131
1137 const SolutionVector& solution(unsigned timeIdx) const
1138 { return solution_[timeIdx]->blockVector(); }
1139
1143 SolutionVector& solution(unsigned timeIdx)
1144 { return solution_[timeIdx]->blockVector(); }
1145
1146 protected:
1150 SolutionVector& mutableSolution(unsigned timeIdx) const
1151 { return solution_[timeIdx]->blockVector(); }
1152
1153 public:
1158 const Linearizer& linearizer() const
1159 { return *linearizer_; }
1160
1165 Linearizer& linearizer()
1166 { return *linearizer_; }
1167
1176 const LocalLinearizer& localLinearizer(unsigned openMpThreadId) const
1177 { return localLinearizer_[openMpThreadId]; }
1181 LocalLinearizer& localLinearizer(unsigned openMpThreadId)
1182 { return localLinearizer_[openMpThreadId]; }
1183
1187 const LocalResidual& localResidual(unsigned openMpThreadId) const
1188 { return asImp_().localLinearizer(openMpThreadId).localResidual(); }
1192 LocalResidual& localResidual(unsigned openMpThreadId)
1193 { return asImp_().localLinearizer(openMpThreadId).localResidual(); }
1194
1202 Scalar primaryVarWeight(unsigned globalDofIdx, unsigned pvIdx) const
1203 {
1204 Scalar absPv = std::abs(asImp_().solution(/*timeIdx=*/1)[globalDofIdx][pvIdx]);
1205 return 1.0/std::max(absPv, 1.0);
1206 }
1207
1214 Scalar eqWeight(unsigned, unsigned) const
1215 { return 1.0; }
1216
1226 Scalar relativeDofError(unsigned vertexIdx,
1227 const PrimaryVariables& pv1,
1228 const PrimaryVariables& pv2) const
1229 {
1230 Scalar result = 0.0;
1231 for (unsigned j = 0; j < numEq; ++j) {
1232 Scalar weight = asImp_().primaryVarWeight(vertexIdx, j);
1233 Scalar eqErr = std::abs((pv1[j] - pv2[j])*weight);
1234 //Scalar eqErr = std::abs(pv1[j] - pv2[j]);
1235 //eqErr *= std::max<Scalar>(1.0, std::abs(pv1[j] + pv2[j])/2);
1236
1237 result = std::max(result, eqErr);
1238 }
1239 return result;
1240 }
1241
1247 bool update()
1248 {
1249 TimerGuard prePostProcessGuard(prePostProcessTimer_);
1250
1251#ifndef NDEBUG
1252 for (unsigned timeIdx = 0; timeIdx < historySize; ++timeIdx) {
1253 // Make sure that the primary variables are defined. Note that because of padding
1254 // bytes, we can't just simply ask valgrind to check the whole solution vectors
1255 // for definedness...
1256 for (size_t i = 0; i < asImp_().solution(/*timeIdx=*/0).size(); ++i) {
1257 asImp_().solution(timeIdx)[i].checkDefined();
1258 }
1259 }
1260#endif // NDEBUG
1261
1262 // make sure all timers are prestine
1265 solveTimer_.halt();
1267
1269 asImp_().updateBegin();
1271
1272 bool converged = false;
1273
1274 try {
1275 converged = newtonMethod_.apply();
1276 }
1277 catch(...) {
1278 prePostProcessTimer_ += newtonMethod_.prePostProcessTimer();
1279 linearizeTimer_ += newtonMethod_.linearizeTimer();
1280 solveTimer_ += newtonMethod_.solveTimer();
1281 updateTimer_ += newtonMethod_.updateTimer();
1282
1283 throw;
1284 }
1285
1286#ifndef NDEBUG
1287 for (unsigned timeIdx = 0; timeIdx < historySize; ++timeIdx) {
1288 // Make sure that the primary variables are defined. Note that because of padding
1289 // bytes, we can't just simply ask valgrind to check the whole solution vectors
1290 // for definedness...
1291 for (size_t i = 0; i < asImp_().solution(/*timeIdx=*/0).size(); ++i) {
1292 asImp_().solution(timeIdx)[i].checkDefined();
1293 }
1294 }
1295#endif // NDEBUG
1296
1297 prePostProcessTimer_ += newtonMethod_.prePostProcessTimer();
1298 linearizeTimer_ += newtonMethod_.linearizeTimer();
1299 solveTimer_ += newtonMethod_.solveTimer();
1300 updateTimer_ += newtonMethod_.updateTimer();
1301
1303 if (converged)
1304 asImp_().updateSuccessful();
1305 else
1306 asImp_().updateFailed();
1308
1309#ifndef NDEBUG
1310 for (unsigned timeIdx = 0; timeIdx < historySize; ++timeIdx) {
1311 // Make sure that the primary variables are defined. Note that because of padding
1312 // bytes, we can't just simply ask valgrind to check the whole solution vectors
1313 // for definedness...
1314 for (size_t i = 0; i < asImp_().solution(/*timeIdx=*/0).size(); ++i) {
1315 asImp_().solution(timeIdx)[i].checkDefined();
1316 }
1317 }
1318#endif // NDEBUG
1319
1320 return converged;
1321 }
1322
1331 { }
1332
1339 { }
1340
1346 { }
1347
1352 {
1353 throw std::invalid_argument("Grid adaptation need to be implemented for "
1354 "specific settings of grid and function spaces");
1355 }
1356
1363 {
1364 // Reset the current solution to the one of the
1365 // previous time step so that we can start the next
1366 // update at a physically meaningful solution.
1367 solution(/*timeIdx=*/0) = solution(/*timeIdx=*/1);
1369
1370#ifndef NDEBUG
1371 for (unsigned timeIdx = 0; timeIdx < historySize; ++timeIdx) {
1372 // Make sure that the primary variables are defined. Note that because of padding
1373 // bytes, we can't just simply ask valgrind to check the whole solution vectors
1374 // for definedness...
1375 for (size_t i = 0; i < asImp_().solution(/*timeIdx=*/0).size(); ++i)
1376 asImp_().solution(timeIdx)[i].checkDefined();
1377 }
1378#endif // NDEBUG
1379 }
1380
1389 {
1390 // at this point we can adapt the grid
1391 if (this->enableGridAdaptation_) {
1392 asImp_().adaptGrid();
1393 }
1394
1395 // make the current solution the previous one.
1396 solution(/*timeIdx=*/1) = solution(/*timeIdx=*/0);
1397
1398 // shift the intensive quantities cache by one position in the
1399 // history
1400 asImp_().shiftIntensiveQuantityCache(/*numSlots=*/1);
1401 }
1402
1410 template <class Restarter>
1411 void serialize(Restarter&)
1412 {
1413 throw std::runtime_error("Not implemented: The discretization chosen for this problem "
1414 "does not support restart files. (serialize() method unimplemented)");
1415 }
1416
1424 template <class Restarter>
1425 void deserialize(Restarter&)
1426 {
1427 throw std::runtime_error("Not implemented: The discretization chosen for this problem "
1428 "does not support restart files. (deserialize() method unimplemented)");
1429 }
1430
1439 template <class DofEntity>
1440 void serializeEntity(std::ostream& outstream,
1441 const DofEntity& dof)
1442 {
1443 unsigned dofIdx = static_cast<unsigned>(asImp_().dofMapper().index(dof));
1444
1445 // write phase state
1446 if (!outstream.good()) {
1447 throw std::runtime_error("Could not serialize degree of freedom "
1448 +std::to_string(dofIdx));
1449 }
1450
1451 for (unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx) {
1452 outstream << solution(/*timeIdx=*/0)[dofIdx][eqIdx] << " ";
1453 }
1454 }
1455
1464 template <class DofEntity>
1465 void deserializeEntity(std::istream& instream,
1466 const DofEntity& dof)
1467 {
1468 unsigned dofIdx = static_cast<unsigned>(asImp_().dofMapper().index(dof));
1469
1470 for (unsigned eqIdx = 0; eqIdx < numEq; ++eqIdx) {
1471 if (!instream.good())
1472 throw std::runtime_error("Could not deserialize degree of freedom "
1473 +std::to_string(dofIdx));
1474 instream >> solution(/*timeIdx=*/0)[dofIdx][eqIdx];
1475 }
1476 }
1477
1481 size_t numGridDof() const
1482 { throw std::logic_error("The discretization class must implement the numGridDof() method!"); }
1483
1487 size_t numAuxiliaryDof() const
1488 {
1489 size_t result = 0;
1490 auto auxModIt = auxEqModules_.begin();
1491 const auto& auxModEndIt = auxEqModules_.end();
1492 for (; auxModIt != auxModEndIt; ++auxModIt)
1493 result += (*auxModIt)->numDofs();
1494
1495 return result;
1496 }
1497
1501 size_t numTotalDof() const
1502 { return asImp_().numGridDof() + numAuxiliaryDof(); }
1503
1508 const DofMapper& dofMapper() const
1509 { throw std::logic_error("The discretization class must implement the dofMapper() method!"); }
1510
1514 const VertexMapper& vertexMapper() const
1515 { return vertexMapper_; }
1516
1520 const ElementMapper& elementMapper() const
1521 { return elementMapper_; }
1522
1528 {
1529 delete linearizer_;
1530 linearizer_ = new Linearizer;
1531 linearizer_->init(simulator_);
1532 }
1533
1537 static std::string discretizationName()
1538 { return ""; }
1539
1545 std::string primaryVarName(unsigned pvIdx) const
1546 {
1547 std::ostringstream oss;
1548 oss << "primary variable_" << pvIdx;
1549 return oss.str();
1550 }
1551
1557 std::string eqName(unsigned eqIdx) const
1558 {
1559 std::ostringstream oss;
1560 oss << "equation_" << eqIdx;
1561 return oss.str();
1562 }
1563
1570 void updatePVWeights(const ElementContext&) const
1571 { }
1572
1577 { outputModules_.push_back(newModule); }
1578
1587 template <class VtkMultiWriter>
1589 const SolutionVector& u,
1590 const GlobalEqVector& deltaU) const
1591 {
1592 using ScalarBuffer = std::vector<double>;
1593
1594 GlobalEqVector globalResid(u.size());
1595 asImp_().globalResidual(globalResid, u);
1596
1597 // create the required scalar fields
1598 size_t numGridDof = asImp_().numGridDof();
1599
1600 // global defect of the two auxiliary equations
1601 ScalarBuffer* def[numEq];
1602 ScalarBuffer* delta[numEq];
1603 ScalarBuffer* priVars[numEq];
1604 ScalarBuffer* priVarWeight[numEq];
1605 ScalarBuffer* relError = writer.allocateManagedScalarBuffer(numGridDof);
1606 ScalarBuffer* normalizedRelError = writer.allocateManagedScalarBuffer(numGridDof);
1607 for (unsigned pvIdx = 0; pvIdx < numEq; ++pvIdx) {
1608 priVars[pvIdx] = writer.allocateManagedScalarBuffer(numGridDof);
1609 priVarWeight[pvIdx] = writer.allocateManagedScalarBuffer(numGridDof);
1610 delta[pvIdx] = writer.allocateManagedScalarBuffer(numGridDof);
1611 def[pvIdx] = writer.allocateManagedScalarBuffer(numGridDof);
1612 }
1613
1614 Scalar minRelErr = 1e30;
1615 Scalar maxRelErr = -1e30;
1616 for (unsigned globalIdx = 0; globalIdx < numGridDof; ++ globalIdx) {
1617 for (unsigned pvIdx = 0; pvIdx < numEq; ++pvIdx) {
1618 (*priVars[pvIdx])[globalIdx] = u[globalIdx][pvIdx];
1619 (*priVarWeight[pvIdx])[globalIdx] = asImp_().primaryVarWeight(globalIdx, pvIdx);
1620 (*delta[pvIdx])[globalIdx] = - deltaU[globalIdx][pvIdx];
1621 (*def[pvIdx])[globalIdx] = globalResid[globalIdx][pvIdx];
1622 }
1623
1624 PrimaryVariables uOld(u[globalIdx]);
1625 PrimaryVariables uNew(uOld);
1626 uNew -= deltaU[globalIdx];
1627
1628 Scalar err = asImp_().relativeDofError(globalIdx, uOld, uNew);
1629 (*relError)[globalIdx] = err;
1630 (*normalizedRelError)[globalIdx] = err;
1631 minRelErr = std::min(err, minRelErr);
1632 maxRelErr = std::max(err, maxRelErr);
1633 }
1634
1635 // do the normalization of the relative error
1636 Scalar alpha = std::max(Scalar{1e-20},
1637 std::max(std::abs(maxRelErr),
1638 std::abs(minRelErr)));
1639 for (unsigned globalIdx = 0; globalIdx < numGridDof; ++ globalIdx)
1640 (*normalizedRelError)[globalIdx] /= alpha;
1641
1642 DiscBaseOutputModule::attachScalarDofData_(writer, *relError, "relative error");
1643 DiscBaseOutputModule::attachScalarDofData_(writer, *normalizedRelError, "normalized relative error");
1644
1645 for (unsigned i = 0; i < numEq; ++i) {
1646 std::ostringstream oss;
1647 oss.str(""); oss << "priVar_" << asImp_().primaryVarName(i);
1648 DiscBaseOutputModule::attachScalarDofData_(writer,
1649 *priVars[i],
1650 oss.str());
1651
1652 oss.str(""); oss << "delta_" << asImp_().primaryVarName(i);
1653 DiscBaseOutputModule::attachScalarDofData_(writer,
1654 *delta[i],
1655 oss.str());
1656
1657 oss.str(""); oss << "weight_" << asImp_().primaryVarName(i);
1658 DiscBaseOutputModule::attachScalarDofData_(writer,
1659 *priVarWeight[i],
1660 oss.str());
1661
1662 oss.str(""); oss << "defect_" << asImp_().eqName(i);
1663 DiscBaseOutputModule::attachScalarDofData_(writer,
1664 *def[i],
1665 oss.str());
1666 }
1667
1668 asImp_().prepareOutputFields();
1669 asImp_().appendOutputFields(writer);
1670 }
1671
1677 {
1678 bool needFullContextUpdate = false;
1679 auto modIt = outputModules_.begin();
1680 const auto& modEndIt = outputModules_.end();
1681 for (; modIt != modEndIt; ++modIt) {
1682 (*modIt)->allocBuffers();
1683 needFullContextUpdate = needFullContextUpdate || (*modIt)->needExtensiveQuantities();
1684 }
1685
1686 // iterate over grid
1687 ThreadedEntityIterator<GridView, /*codim=*/0> threadedElemIt(gridView());
1688#ifdef _OPENMP
1689#pragma omp parallel
1690#endif
1691 {
1692 ElementContext elemCtx(simulator_);
1693 ElementIterator elemIt = threadedElemIt.beginParallel();
1694 for (; !threadedElemIt.isFinished(elemIt); elemIt = threadedElemIt.increment()) {
1695 const auto& elem = *elemIt;
1696 if (elem.partitionType() != Dune::InteriorEntity)
1697 // ignore non-interior entities
1698 continue;
1699
1700 if (needFullContextUpdate)
1701 elemCtx.updateAll(elem);
1702 else {
1703 elemCtx.updatePrimaryStencil(elem);
1704 elemCtx.updatePrimaryIntensiveQuantities(/*timeIdx=*/0);
1705 }
1706
1707 // we cannot reuse the "modIt" variable here because the code here might
1708 // be threaded and "modIt" is is the same for all threads, i.e., if a
1709 // given thread modifies it, the changes affect all threads.
1710 auto modIt2 = outputModules_.begin();
1711 for (; modIt2 != modEndIt; ++modIt2)
1712 (*modIt2)->processElement(elemCtx);
1713 }
1714 }
1715 }
1716
1722 {
1723 auto modIt = outputModules_.begin();
1724 const auto& modEndIt = outputModules_.end();
1725 for (; modIt != modEndIt; ++modIt)
1726 (*modIt)->commitBuffers(writer);
1727 }
1728
1732 const GridView& gridView() const
1733 { return gridView_; }
1734
1747 {
1748 auxMod->setDofOffset(numTotalDof());
1749 auxEqModules_.push_back(auxMod);
1750
1751 // resize the solutions
1753 && !std::is_same<DiscreteFunction, BlockVectorWrapper>::value)
1754 {
1755 throw std::invalid_argument("Problems which require auxiliary modules cannot be used in"
1756 " conjunction with dune-fem");
1757 }
1758
1759 size_t numDof = numTotalDof();
1760 for (unsigned timeIdx = 0; timeIdx < historySize; ++timeIdx)
1761 solution(timeIdx).resize(numDof);
1762
1763 auxMod->applyInitial();
1764 }
1765
1772 {
1773 auxEqModules_.clear();
1774 linearizer_->eraseMatrix();
1775 newtonMethod_.eraseMatrix();
1776 }
1777
1781 size_t numAuxiliaryModules() const
1782 { return auxEqModules_.size(); }
1783
1788 { return auxEqModules_[auxEqModIdx]; }
1789
1793 const BaseAuxiliaryModule<TypeTag>* auxiliaryModule(unsigned auxEqModIdx) const
1794 { return auxEqModules_[auxEqModIdx]; }
1795
1801
1803 { return prePostProcessTimer_; }
1804
1805 const Timer& linearizeTimer() const
1806 { return linearizeTimer_; }
1807
1808 const Timer& solveTimer() const
1809 { return solveTimer_; }
1810
1811 const Timer& updateTimer() const
1812 { return updateTimer_; }
1813
1814 template<class Serializer>
1815 void serializeOp(Serializer& serializer)
1816 {
1818 using Helper = typename BaseDiscretization::template SerializeHelper<Serializer>;
1819 Helper::serializeOp(serializer, solution_);
1820 }
1821
1822 bool operator==(const FvBaseDiscretization& rhs) const
1823 {
1824 return std::equal(this->solution_.begin(), this->solution_.end(),
1825 rhs.solution_.begin(), rhs.solution_.end(),
1826 [](const auto& x, const auto& y)
1827 {
1828 return *x == *y;
1829 });
1830 }
1831
1832protected:
1834 {
1835 // allocate the storage cache
1836 if (enableStorageCache()) {
1837 size_t numDof = asImp_().numGridDof();
1838 for (unsigned timeIdx = 0; timeIdx < historySize; ++timeIdx) {
1839 storageCache_[timeIdx].resize(numDof);
1840 }
1841 }
1842
1843 // allocate the intensive quantities cache
1845 size_t numDof = asImp_().numGridDof();
1846 for(unsigned timeIdx=0; timeIdx<historySize; ++timeIdx) {
1847 intensiveQuantityCache_[timeIdx].resize(numDof);
1848 intensiveQuantityCacheUpToDate_[timeIdx].resize(numDof);
1850 }
1851 }
1852 }
1853 template <class Context>
1854 void supplementInitialSolution_(PrimaryVariables&,
1855 const Context&,
1856 unsigned,
1857 unsigned)
1858 { }
1859
1868 {
1869 // add the output modules available on all model
1871 this->outputModules_.push_back(mod);
1872 }
1873
1877 LocalResidual& localResidual_()
1878 { return localLinearizer_.localResidual(); }
1879
1883 bool verbose_() const
1884 { return gridView_.comm().rank() == 0; }
1885
1886 Implementation& asImp_()
1887 { return *static_cast<Implementation*>(this); }
1888 const Implementation& asImp_() const
1889 { return *static_cast<const Implementation*>(this); }
1890
1891 // the problem we want to solve. defines the constitutive
1892 // relations, matxerial laws, etc.
1893 Simulator& simulator_;
1894
1895 // the representation of the spatial domain of the problem
1896 GridView gridView_;
1897
1898 // the mappers for element and vertex entities to global indices
1899 ElementMapper elementMapper_;
1900 VertexMapper vertexMapper_;
1901
1902 // a vector with all auxiliary equations to be considered
1903 std::vector<BaseAuxiliaryModule<TypeTag>*> auxEqModules_;
1904
1905 NewtonMethod newtonMethod_;
1906
1911
1912 // calculates the local jacobian matrix for a given element
1913 std::vector<LocalLinearizer> localLinearizer_;
1914 // Linearizes the problem at the current time step using the
1915 // local jacobian
1916 Linearizer *linearizer_;
1917
1918 // cur is the current iterative solution, prev the converged
1919 // solution of the previous time step
1920 mutable IntensiveQuantitiesVector intensiveQuantityCache_[historySize];
1921 // while these are logically bools, concurrent writes to vector<bool> are not thread safe.
1922 mutable std::vector<unsigned char> intensiveQuantityCacheUpToDate_[historySize];
1923
1924 mutable std::array< std::unique_ptr< DiscreteFunction >, historySize > solution_;
1925
1926 std::list<BaseOutputModule<TypeTag>*> outputModules_;
1927
1929 std::vector<Scalar> dofTotalVolume_;
1930 std::vector<bool> isLocalDof_;
1931
1932 mutable GlobalEqVector storageCache_[historySize];
1933
1938};
1939
1945template<class TypeTag>
1947{
1951
1952 static constexpr unsigned historySize = getPropValue<TypeTag, Properties::TimeDiscHistorySize>();
1953
1954public:
1955 template<class Serializer>
1957 template<class SolutionType>
1958 static void serializeOp(Serializer& serializer,
1959 SolutionType& solution)
1960 {
1961 for (auto& sol : solution) {
1962 serializer(*sol);
1963 }
1964 }
1965 };
1966
1967 FvBaseDiscretizationNoAdapt(Simulator& simulator)
1968 : ParentType(simulator)
1969 {
1970 if (this->enableGridAdaptation_) {
1971 throw std::invalid_argument("Grid adaptation need to use"
1972 " BaseDiscretization = FvBaseDiscretizationFemAdapt"
1973 " which currently requires the presence of the"
1974 " dune-fem module");
1975 }
1976 size_t numDof = this->asImp_().numGridDof();
1977 for (unsigned timeIdx = 0; timeIdx < historySize; ++timeIdx) {
1978 this->solution_[timeIdx] = std::make_unique<DiscreteFunction>("solution", numDof);
1979 }
1980 }
1981};
1982
1983} // namespace Opm
1984
1985#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:79
The base class for writer modules.
Definition: baseoutputmodule.hh:67
The base class for all output writers.
Definition: baseoutputwriter.hh:44
Represents all quantities which available on boundary segments.
Definition: fvbaseboundarycontext.hh:44
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:46
Definition: fvbasediscretization.hh:344
const SolutionVector & blockVector() const
Definition: fvbasediscretization.hh:366
SolutionVector blockVector_
Definition: fvbasediscretization.hh:346
BlockVectorWrapper(const std::string &, const size_t size)
Definition: fvbasediscretization.hh:348
void serializeOp(Serializer &serializer)
Definition: fvbasediscretization.hh:376
static BlockVectorWrapper serializationTestObject()
Definition: fvbasediscretization.hh:354
SolutionVector & blockVector()
Definition: fvbasediscretization.hh:364
bool operator==(const BlockVectorWrapper &wrapper) const
Definition: fvbasediscretization.hh:369
The base class for the finite volume discretization schemes without adaptation.
Definition: fvbasediscretization.hh:1947
FvBaseDiscretizationNoAdapt(Simulator &simulator)
Definition: fvbasediscretization.hh:1967
The base class for the finite volume discretization schemes.
Definition: fvbasediscretization.hh:294
Timer linearizeTimer_
Definition: fvbasediscretization.hh:1908
LocalLinearizer & localLinearizer(unsigned openMpThreadId)
Definition: fvbasediscretization.hh:1181
size_t numAuxiliaryDof() const
Returns the number of degrees of freedom (DOFs) of the auxiliary equations.
Definition: fvbasediscretization.hh:1487
void prepareOutputFields() const
Prepare the quantities relevant for the current solution to be appended to the output writers.
Definition: fvbasediscretization.hh:1676
void shiftIntensiveQuantityCache(unsigned numSlots=1)
Move the intensive quantities for a given time index to the back.
Definition: fvbasediscretization.hh:781
void invalidateAndUpdateIntensiveQuantities(unsigned timeIdx) const
Definition: fvbasediscretization.hh:723
void adaptGrid()
Called by the update() method when the grid should be refined.
Definition: fvbasediscretization.hh:1351
std::vector< BaseAuxiliaryModule< TypeTag > * > auxEqModules_
Definition: fvbasediscretization.hh:1903
~FvBaseDiscretization()
Definition: fvbasediscretization.hh:428
const Implementation & asImp_() const
Definition: fvbasediscretization.hh:1888
void addAuxiliaryModule(BaseAuxiliaryModule< TypeTag > *auxMod)
Add a module for an auxiliary equation.
Definition: fvbasediscretization.hh:1746
void setIntensiveQuantitiesCacheEntryValidity(unsigned globalIdx, unsigned timeIdx, bool newValue) const
Invalidate the cache for a given intensive quantities object.
Definition: fvbasediscretization.hh:699
void finishInit()
Apply the initial conditions to the model.
Definition: fvbasediscretization.hh:473
void prefetch(const Element &) const
Allows to improve the performance by prefetching all data which is associated with a given element.
Definition: fvbasediscretization.hh:603
bool enableStorageCache_
Definition: fvbasediscretization.hh:1936
void resizeAndResetIntensiveQuantitiesCache_()
Definition: fvbasediscretization.hh:1833
std::vector< Scalar > dofTotalVolume_
Definition: fvbasediscretization.hh:1929
void updateSuccessful()
Called by the update() method if it was successful.
Definition: fvbasediscretization.hh:1345
static std::string discretizationName()
Returns a string of discretization's human-readable name.
Definition: fvbasediscretization.hh:1537
BaseAuxiliaryModule< TypeTag > * auxiliaryModule(unsigned auxEqModIdx)
Returns a given module for auxiliary equations.
Definition: fvbasediscretization.hh:1787
bool isLocalDof(unsigned globalIdx) const
Returns if the overlap of the volume ofa degree of freedom is non-zero.
Definition: fvbasediscretization.hh:1122
bool operator==(const FvBaseDiscretization &rhs) const
Definition: fvbasediscretization.hh:1822
void serializeOp(Serializer &serializer)
Definition: fvbasediscretization.hh:1815
std::vector< bool > isLocalDof_
Definition: fvbasediscretization.hh:1930
LocalResidual & localResidual_()
Reference to the local residal object.
Definition: fvbasediscretization.hh:1877
void registerOutputModules_()
Register all output modules which make sense for the model.
Definition: fvbasediscretization.hh:1867
bool enableGridAdaptation() const
Returns whether the grid ought to be adapted to the solution during the simulation.
Definition: fvbasediscretization.hh:542
const NewtonMethod & newtonMethod() const
Returns the newton method object.
Definition: fvbasediscretization.hh:617
SolutionVector & mutableSolution(unsigned timeIdx) const
Definition: fvbasediscretization.hh:1150
void advanceTimeLevel()
Called by the problem if a time integration was successful, post processing of the solution is done a...
Definition: fvbasediscretization.hh:1388
NewtonMethod & newtonMethod()
Returns the newton method object.
Definition: fvbasediscretization.hh:611
const VertexMapper & vertexMapper() const
Returns the mapper for vertices to indices.
Definition: fvbasediscretization.hh:1514
const EqVector & cachedStorage(unsigned globalIdx, unsigned timeIdx) const
Retrieve an entry of the cache for the storage term.
Definition: fvbasediscretization.hh:836
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:1570
const Timer & solveTimer() const
Definition: fvbasediscretization.hh:1808
void updateFailed()
Called by the update() method if it was unsuccessful. This is primary a hook which the actual model c...
Definition: fvbasediscretization.hh:1362
void updateBegin()
Called by the update() method before it tries to apply the newton method. This is primary a hook whic...
Definition: fvbasediscretization.hh:1338
Scalar globalResidual(GlobalEqVector &dest) const
Compute the global residual for the current solution vector.
Definition: fvbasediscretization.hh:882
LocalResidual & localResidual(unsigned openMpThreadId)
Definition: fvbasediscretization.hh:1192
void serializeEntity(std::ostream &outstream, const DofEntity &dof)
Write the current solution for a degree of freedom to a restart file.
Definition: fvbasediscretization.hh:1440
void setEnableStorageCache(bool enableStorageCache)
Set the value of enable storage cache.
Definition: fvbasediscretization.hh:823
std::string eqName(unsigned eqIdx) const
Given an equation index, return a human readable name.
Definition: fvbasediscretization.hh:1557
std::list< BaseOutputModule< TypeTag > * > outputModules_
Definition: fvbasediscretization.hh:1926
Scalar eqWeight(unsigned, unsigned) const
Returns the relative weight of an equation.
Definition: fvbasediscretization.hh:1214
const Timer & prePostProcessTimer() const
Definition: fvbasediscretization.hh:1802
Scalar primaryVarWeight(unsigned globalDofIdx, unsigned pvIdx) const
Returns the relative weight of a primary variable for calculating relative errors.
Definition: fvbasediscretization.hh:1202
void deserialize(Restarter &)
Deserializes the state of the model.
Definition: fvbasediscretization.hh:1425
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:995
std::array< std::unique_ptr< DiscreteFunction >, historySize > solution_
Definition: fvbasediscretization.hh:1924
Scalar gridTotalVolume() const
Returns the volume of the whole grid which represents the spatial domain.
Definition: fvbasediscretization.hh:1129
Timer updateTimer_
Definition: fvbasediscretization.hh:1910
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:635
const Timer & updateTimer() const
Definition: fvbasediscretization.hh:1811
const Linearizer & linearizer() const
Returns the operator linearizer for the global jacobian of the problem.
Definition: fvbasediscretization.hh:1158
void updateCachedStorage(unsigned globalIdx, unsigned timeIdx, const EqVector &value) const
Set an entry of the cache for the storage term.
Definition: fvbasediscretization.hh:853
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:1588
Scalar relativeDofError(unsigned vertexIdx, const PrimaryVariables &pv1, const PrimaryVariables &pv2) const
Returns the relative error between two vectors of primary variables.
Definition: fvbasediscretization.hh:1226
bool enableGridAdaptation_
Definition: fvbasediscretization.hh:1934
Scalar globalResidual(GlobalEqVector &dest, const SolutionVector &u) const
Compute the global residual for an arbitrary solution vector.
Definition: fvbasediscretization.hh:866
SolutionVector & solution(unsigned timeIdx)
Definition: fvbasediscretization.hh:1143
void addOutputModule(BaseOutputModule< TypeTag > *newModule)
Add an module for writing visualization output after a timestep.
Definition: fvbasediscretization.hh:1576
Timer prePostProcessTimer_
Definition: fvbasediscretization.hh:1907
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:1465
Timer solveTimer_
Definition: fvbasediscretization.hh:1909
void supplementInitialSolution_(PrimaryVariables &, const Context &, unsigned, unsigned)
Definition: fvbasediscretization.hh:1854
const LocalLinearizer & localLinearizer(unsigned openMpThreadId) const
Returns the local jacobian which calculates the local stiffness matrix for an arbitrary element.
Definition: fvbasediscretization.hh:1176
const Timer & linearizeTimer() const
Definition: fvbasediscretization.hh:1805
void invalidateAndUpdateIntensiveQuantities(unsigned timeIdx, const GridViewType &gridView) const
Definition: fvbasediscretization.hh:744
bool update()
Try to progress the model to the next timestep.
Definition: fvbasediscretization.hh:1247
void clearAuxiliaryModules()
Causes the list of auxiliary equations to be cleared.
Definition: fvbasediscretization.hh:1771
bool enableIntensiveQuantityCache_
Definition: fvbasediscretization.hh:1935
std::vector< unsigned char > intensiveQuantityCacheUpToDate_[historySize]
Definition: fvbasediscretization.hh:1922
const ElementMapper & elementMapper() const
Returns the mapper for elements to indices.
Definition: fvbasediscretization.hh:1520
size_t numGridDof() const
Returns the number of degrees of freedom (DOFs) for the computational grid.
Definition: fvbasediscretization.hh:1481
void syncOverlap()
Syncronize the values of the primary variables on the degrees of freedom that overlap with the neighb...
Definition: fvbasediscretization.hh:1330
void appendOutputFields(BaseOutputWriter &writer) const
Append the quantities relevant for the current solution to an output writer.
Definition: fvbasediscretization.hh:1721
ElementMapper elementMapper_
Definition: fvbasediscretization.hh:1899
NewtonMethod newtonMethod_
Definition: fvbasediscretization.hh:1905
void applyInitialSolution()
Applies the initial solution for all degrees of freedom to which the model applies.
Definition: fvbasediscretization.hh:549
Implementation & asImp_()
Definition: fvbasediscretization.hh:1886
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:681
std::string primaryVarName(unsigned pvIdx) const
Given an primary variable index, return a human readable name.
Definition: fvbasediscretization.hh:1545
GlobalEqVector storageCache_[historySize]
Definition: fvbasediscretization.hh:1932
void invalidateIntensiveQuantitiesCache(unsigned timeIdx) const
Invalidate the whole intensive quantity cache for time index.
Definition: fvbasediscretization.hh:714
Linearizer & linearizer()
Returns the object which linearizes the global system of equations at the current solution.
Definition: fvbasediscretization.hh:1165
const BaseAuxiliaryModule< TypeTag > * auxiliaryModule(unsigned auxEqModIdx) const
Returns a given module for auxiliary equations.
Definition: fvbasediscretization.hh:1793
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:943
Linearizer * linearizer_
Definition: fvbasediscretization.hh:1916
GridView gridView_
Definition: fvbasediscretization.hh:1896
Scalar dofTotalVolume(unsigned globalIdx) const
Returns the volume of a given control volume.
Definition: fvbasediscretization.hh:1114
static void registerParameters()
Register all run-time parameters for the model.
Definition: fvbasediscretization.hh:442
const SolutionVector & solution(unsigned timeIdx) const
Reference to the solution at a given history index as a block vector.
Definition: fvbasediscretization.hh:1137
bool verbose_() const
Returns whether messages should be printed.
Definition: fvbasediscretization.hh:1883
Simulator & simulator_
Definition: fvbasediscretization.hh:1893
const LocalResidual & localResidual(unsigned openMpThreadId) const
Returns the object to calculate the local residual function.
Definition: fvbasediscretization.hh:1187
Scalar gridTotalVolume_
Definition: fvbasediscretization.hh:1928
const DofMapper & dofMapper() const
Mapper to convert the Dune entities of the discretization's degrees of freedoms are to indices.
Definition: fvbasediscretization.hh:1508
bool storeIntensiveQuantities() const
Returns true if the cache for intensive quantities is enabled.
Definition: fvbasediscretization.hh:1799
std::vector< LocalLinearizer > localLinearizer_
Definition: fvbasediscretization.hh:1913
void serialize(Restarter &)
Serializes the current state of the model.
Definition: fvbasediscretization.hh:1411
IntensiveQuantitiesVector intensiveQuantityCache_[historySize]
Definition: fvbasediscretization.hh:1920
bool enableThermodynamicHints_
Definition: fvbasediscretization.hh:1937
size_t numTotalDof() const
Returns the total number of degrees of freedom (i.e., grid plux auxiliary DOFs)
Definition: fvbasediscretization.hh:1501
VertexMapper vertexMapper_
Definition: fvbasediscretization.hh:1900
void resetLinearizer()
Resets the Jacobian matrix linearizer, so that the boundary types can be altered.
Definition: fvbasediscretization.hh:1527
bool enableStorageCache() const
Returns true iff the storage term is cached.
Definition: fvbasediscretization.hh:814
size_t numAuxiliaryModules() const
Returns the number of modules for auxiliary equations.
Definition: fvbasediscretization.hh:1781
const GridView & gridView() const
Reference to the grid view of the spatial domain.
Definition: fvbasediscretization.hh:1732
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:655
This class stores an array of IntensiveQuantities objects, one intensive quantities object for each o...
Definition: fvbaseelementcontext.hh:52
Provide the properties at a face which make sense indepentently of the conserved quantities.
Definition: fvbaseextensivequantities.hh:46
This class calculates gradients of arbitrary quantities at flux integration points using the two-poin...
Definition: fvbasegradientcalculator.hh:47
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:71
Element-wise caculation of the residual matrix for models based on a finite volume spatial discretiza...
Definition: fvbaselocalresidual.hh:58
Represents the primary variables used by the a model.
Definition: fvbaseprimaryvariables.hh:52
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:129
Manages the initializing and running of time dependent problems.
Definition: simulator.hh:102
Simplifies multi-threaded capabilities.
Definition: threadmanager.hh:47
static unsigned maxThreads()
Return the maximum number of threads of the current process.
Definition: threadmanager.hh:118
static unsigned threadId()
Return the index of the current OpenMP thread.
Definition: threadmanager.hh:124
Provides an STL-iterator like interface to iterate over the enties of a GridView in OpenMP threaded a...
Definition: threadedentityiterator.hh:43
bool isFinished(const EntityIterator &it) const
Definition: threadedentityiterator.hh:67
EntityIterator increment()
Definition: threadedentityiterator.hh:80
EntityIterator beginParallel()
Definition: threadedentityiterator.hh:55
A simple class which makes sure that a timer gets stopped if an exception is thrown.
Definition: timerguard.hh:41
Provides an encapsulation to measure the system time.
Definition: timer.hh:49
void start()
Start counting the time resources used by the simulation.
Definition: timer.hh:62
void halt()
Stop the measurement reset all timing values.
Definition: timer.hh:99
double stop()
Stop counting the time resources.
Definition: timer.hh:73
Simplifies writing multi-file VTK datasets.
Definition: vtkmultiwriter.hh:66
ScalarBuffer * allocateManagedScalarBuffer(size_t numEntities)
Allocate a managed buffer for a scalar field.
Definition: vtkmultiwriter.hh:203
VTK output module for the fluid composition.
Definition: vtkprimaryvarsmodule.hh:55
static void registerParameters()
Register all run-time parameters for the Vtk output module.
Definition: vtkprimaryvarsmodule.hh:78
Definition: alignedallocator.hh:114
Declare the properties used by the infrastructure code of the finite volume discretizations.
Provides data handles for parallel communication which operate on DOFs.
auto Get(bool errorIfNotRegistered=true)
Retrieve a runtime parameter.
Definition: parametersystem.hh:840
Declares the parameters for the black oil model.
Definition: fvbaseprimaryvariables.hh:141
Definition: blackoilmodel.hh:72
Definition: blackoilboundaryratevector.hh:37
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:235
Definition: fvbasediscretization.hh:1956
static void serializeOp(Serializer &serializer, SolutionType &solution)
Definition: fvbasediscretization.hh:1958
Definition: fvbasediscretization.hh:268
GetPropType< TypeTag, Properties::GridView > GridView
Definition: fvbasediscretization.hh:109
GetPropType< TypeTag, Properties::DofMapper > DofMapper
Definition: fvbasediscretization.hh:108
The class which marks the border indices associated with the degrees of freedom on a process boundary...
Definition: basicproperties.hh:125
The secondary variables of a boundary segment.
Definition: fvbaseproperties.hh:143
GetPropType< TypeTag, Properties::RateVector > type
Definition: fvbasediscretization.hh:156
Type of object for specifying boundary conditions.
Definition: fvbaseproperties.hh:119
The secondary variables of a constraint degree of freedom.
Definition: fvbaseproperties.hh:146
The class which represents a constraint degree of freedom.
Definition: fvbaseproperties.hh:122
The part of the extensive quantities which is specific to the spatial discretization.
Definition: fvbaseproperties.hh:160
The discretization specific part of the intensive quantities.
Definition: fvbaseproperties.hh:136
The discretization specific part of the local residual.
Definition: fvbaseproperties.hh:91
typename BaseDiscretization::BlockVectorWrapper type
Definition: fvbasediscretization.hh:279
Definition: fvbaseproperties.hh:77
The secondary variables of all degrees of freedom in an element's stencil.
Definition: fvbaseproperties.hh:140
Dune::BlockVector< GetPropType< TypeTag, Properties::EqVector > > type
Definition: fvbasediscretization.hh:170
A vector of holding a quantity for each equation for each DOF of an element.
Definition: fvbaseproperties.hh:112
Dune::MultipleCodimMultipleGeomTypeMapper< GetPropType< TypeTag, Properties::GridView > > type
Definition: fvbasediscretization.hh:102
The mapper to find the global index of an element.
Definition: fvbaseproperties.hh:213
Specify whether the some degrees of fredom can be constraint.
Definition: fvbaseproperties.hh:199
Specify if experimental features should be enabled or not.
Definition: fvbaseproperties.hh:241
Dune::FieldVector< GetPropType< TypeTag, Properties::Scalar >, getPropValue< TypeTag, Properties::NumEq >()> type
Definition: fvbasediscretization.hh:139
A vector of holding a quantity for each equation (usually at a given spatial location)
Definition: fvbaseproperties.hh:109
Specify whether the storage terms use extensive quantities or not.
Definition: fvbaseproperties.hh:233
Dune::BlockVector< GetPropType< TypeTag, Properties::EqVector > > type
Definition: fvbasediscretization.hh:177
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:152
The secondary variables within a sub-control volume.
Definition: fvbaseproperties.hh:133
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:130
GetPropType< TypeTag, Properties::EqVector > type
Definition: fvbasediscretization.hh:149
Vector containing volumetric or areal rates of quantities.
Definition: fvbaseproperties.hh:116
Manages the simulation time.
Definition: basicproperties.hh:116
Dune::BlockVector< GetPropType< TypeTag, Properties::PrimaryVariables > > type
Definition: fvbasediscretization.hh:191
Vector containing all primary variables of the grid.
Definition: fvbaseproperties.hh:126
The OpenMP threads manager.
Definition: fvbaseproperties.hh:174
The history size required by the time discretization.
Definition: fvbaseproperties.hh:225
a tag to mark properties as undefined
Definition: propertysystem.hh:40
Definition: fvbaseproperties.hh:181
Specify whether to use volumetric residuals or not.
Definition: fvbaseproperties.hh:237
Dune::MultipleCodimMultipleGeomTypeMapper< GetPropType< TypeTag, Properties::GridView > > type
Definition: fvbasediscretization.hh:97
The mapper to find the global index of a vertex.
Definition: fvbaseproperties.hh:207
Specify the format the VTK output is written to disk.
Definition: fvbaseproperties.hh:195