version 3.11-dev
Loading...
Searching...
No Matches
finelevelview.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// SPDX-FileCopyrightText: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
12
13#ifndef DUMUX_TWOPVE_FINE_LEVEL_VIEW_HH
14#define DUMUX_TWOPVE_FINE_LEVEL_VIEW_HH
15
16#include <algorithm>
17#include <cmath>
18#include <cstddef>
19#include <memory>
20#include <type_traits>
21#include <vector>
22
23#include <dune/common/exceptions.hh>
24#include <dune/grid/common/rangegenerators.hh>
25
32
33namespace Dumux {
34
41template<class Scalar>
47
64template<class CoarseGridGeometry, class FineGridGeometry, class Scalar, class FluidSystem, class Indices, class SolutionVector, class SpatialParamsFine>
66{
67 using GridView = typename FineGridGeometry::GridView;
68 using CoarseGridView = typename CoarseGridGeometry::GridView;
69 using Element = typename CoarseGridView::template Codim<0>::Entity;
70 using QuantityReconstructor = TwoPVEQuantityReconstruction<Scalar, FluidSystem>;
71 static constexpr int pressureIdx = Indices::pressureIdx;
72 static constexpr int saturationIdx = Indices::saturationIdx;
73 static constexpr int wettingPhaseIdx = FluidSystem::phase0Idx;
74 static constexpr int nonwettingPhaseIdx = FluidSystem::phase1Idx;
75 static constexpr int dim = GridView::dimension;
76 static constexpr int dimWorld = GridView::dimensionworld;
77 static_assert(dim == 2 || dim == 3, "TwoPVEFineLevelView only supports two- and three-dimensional grids");
78 using ColumnState = TwoPVEColumnState<Scalar>;
80
81 using PhaseDensities = TwoPVE::PhaseDensitiesData<Scalar>;
82 using ResidualSaturations = TwoPVE::ResidualSaturationsData<Scalar>;
83 using BrooksCoreyParameters = TwoPVE::BrooksCoreyParametersData<Scalar>;
84
85public:
88
96 TwoPVEFineLevelView(std::shared_ptr<const FineGridGeometry> gridGeometry,
97 std::shared_ptr<const CoarseGridGeometry> gridGeometryCoarse,
98 std::shared_ptr<const SpatialParamsFine> spatialParamsFine)
99 : gridGeometryFine_(gridGeometry),
100 gridGeometryCoarse_(gridGeometryCoarse),
101 spatialParamsFine_(spatialParamsFine),
102 quantityReconstructor_{},
103 columnMapping_(gridGeometryCoarse, gridGeometry),
104 solution_(gridGeometryFine_->numDofs()),
105 fineLevelFields_(gridGeometryFine_->numDofs()),
106 fineCellHeight_(computeFineCellHeight_()),
107 columnHistory_(gridGeometryCoarse_->numDofs())
108 {
109 const Scalar domainHeight = gridGeometryFine_->bBoxMax()[dim-1] - gridGeometryFine_->bBoxMin()[dim-1];
110 checkColumns_(domainHeight);
111 for (auto& history : columnHistory_)
112 {
113 // initially there is no gas in the columns
114 history.gasPlumeDistance = domainHeight;
115 history.minimumGasPlumeDistance = domainHeight;
116 }
117 }
118
122 Scalar fineCellHeight() const
123 {
124 return fineCellHeight_;
125 }
126
130 const SpatialParamsFine& spatialParams() const
131 {
132 return *spatialParamsFine_;
133 }
134
138 std::shared_ptr<const SpatialParamsFine> spatialParamsPtr() const
139 {
140 return spatialParamsFine_;
141 }
142
146 const ColumnMapping& columnMap() const
147 {
148 return columnMapping_;
149 }
150
154 const FineGridGeometry& gridGeometry() const
155 {
156 return *gridGeometryFine_;
157 }
158
162 const CoarseGridGeometry& gridGeometryCoarse() const
163 {
164 return *gridGeometryCoarse_;
165 }
166
170 const SolutionVector& solution() const
171 {
172 return solution_;
173 }
174
178 SolutionVector& solution()
179 {
180 return solution_;
181 }
182
186 const QuantityReconstructor& quantityReconstructor() const
187 {
188 return quantityReconstructor_;
189 }
190
194 const auto& fields() const
195 {
196 return fineLevelFields_;
197 }
198
206 template<class PrimaryVariables, class SpatialParamsCoarse>
207 ColumnState makeColumnState(const Element& coarseElement,
208 const PrimaryVariables& coarsePriVars,
209 const SpatialParamsCoarse& coarseSpatialParams) const
210 {
211 ColumnState state;
212
213 const auto coarsePosition = coarseElement.geometry().center();
214 const auto columnIdx = gridGeometryCoarse_->elementMapper().index(coarseElement);
215
216 state.pwCoarse = coarsePriVars[pressureIdx];
217 state.swCoarse = 1.0 - coarsePriVars[saturationIdx];
218 state.temperature = coarseSpatialParams.temperatureAtPos(coarsePosition);
219 const auto& history = columnHistory_[columnIdx];
220
221 state.domainHeight = gridGeometryFine_->bBoxMax()[dim - 1] - gridGeometryFine_->bBoxMin()[dim - 1];
222
223 const auto fluidMatrixInteraction = coarseSpatialParams.fluidMatrixInteractionAtPos(coarsePosition);
224 using BasicParams = std::decay_t<decltype(fluidMatrixInteraction.pcSwCurve().basicParams())>;
225 static_assert(std::is_same_v<BasicParams, FluidMatrix::BrooksCorey::Params<Scalar>>, "The VE reconstruction requires a Brooks-Corey material law");
226 const auto& brooksCoreyParams = fluidMatrixInteraction.pcSwCurve().basicParams();
227 const auto& absoluteSaturationParams = fluidMatrixInteraction.pcSwCurve().effToAbsParams();
228 state.swr = absoluteSaturationParams.swr();
229 state.snr = absoluteSaturationParams.snr();
230 state.brooksCoreyLambda = brooksCoreyParams.lambda();
231 state.entryPressure = brooksCoreyParams.pcEntry();
232 const auto& fineElement = columnMapping_.column(columnIdx).front();
233 const auto& gravity = spatialParamsFine_->gravity(fineElement.geometry().center());
234 for (int dirIdx = 0; dirIdx < dimWorld - 1; ++dirIdx)
235 if (gravity[dirIdx] != 0.0)
236 DUNE_THROW(Dune::InvalidStateException, "The VE model requires gravity to be aligned with the vertical coordinate axis");
237 state.gravityNorm = gravity.two_norm();
238
239 // the fluid properties of both phases are evaluated at the coarse-level wetting-phase pressure
241 fluidState.setTemperature(state.temperature);
242 fluidState.setPressure(wettingPhaseIdx, state.pwCoarse);
243 fluidState.setPressure(nonwettingPhaseIdx, state.pwCoarse);
244 state.densityW = FluidSystem::density(fluidState, wettingPhaseIdx);
245 state.viscosityW = FluidSystem::viscosity(fluidState, wettingPhaseIdx);
246 state.densityNw = FluidSystem::density(fluidState, nonwettingPhaseIdx);
247 state.viscosityNw = FluidSystem::viscosity(fluidState, nonwettingPhaseIdx);
248
249 state.gasPlumeDistance = quantityReconstructor_.computeGasPlumeDist(
250 PhaseDensities{state.densityW, state.densityNw},
251 ResidualSaturations{state.swr, state.snr},
252 state.gravityNorm,
253 state.domainHeight,
254 state.swCoarse,
255 history.minimumGasPlumeDistance,
256 BrooksCoreyParameters{state.brooksCoreyLambda, state.entryPressure});
257 using std::min;
258 state.minimumGasPlumeDistance = min(history.minimumGasPlumeDistance, state.gasPlumeDistance);
259
260 return state;
261 }
262
272 template<class ProblemCoarse>
273 void updateSol(const ProblemCoarse& coarseProblem,
274 const SolutionVector& coarseSolution)
275 {
276 const auto& coarseSpatialParams = coarseProblem.spatialParams();
277
278 for (const auto& coarseElement : elements(gridGeometryCoarse_->gridView()))
279 {
280 const auto coarseIdx = gridGeometryCoarse_->elementMapper().index(coarseElement);
281 const auto& coarsePriVars = coarseSolution[coarseIdx];
282 const auto columnState = makeColumnState(coarseElement, coarsePriVars, coarseSpatialParams);
283
284 auto& history = columnHistory_[coarseIdx];
285 history.gasPlumeDistance = columnState.gasPlumeDistance;
286 history.minimumGasPlumeDistance = columnState.minimumGasPlumeDistance;
287
288 const auto& column = columnMapping_.column(coarseIdx);
289 for (const auto& fineElement : column)
290 {
291 const auto fineIdx = gridGeometryFine_->elementMapper().index(fineElement);
292
293 FineLevelElementState fineElementState;
294 fineElementState.update(fineElement, columnState, *spatialParamsFine_, quantityReconstructor_, fineCellHeight_);
295 solution_[fineIdx][pressureIdx] = fineElementState.pressure(wettingPhaseIdx);
296 solution_[fineIdx][saturationIdx] = fineElementState.saturation(nonwettingPhaseIdx);
297 fineLevelFields_.set(fineIdx, fineElementState);
298 }
299 }
300 }
301
302private:
303
310 template<class ElementGeometry>
311 Scalar elementExtent_(const ElementGeometry& geometry, const int direction) const
312 {
313 using std::max; using std::min;
314 Scalar lower = geometry.corner(0)[direction];
315 Scalar upper = lower;
316
317 for (int cornerIdx = 1; cornerIdx < geometry.corners(); ++cornerIdx)
318 {
319 const Scalar coordinate = geometry.corner(cornerIdx)[direction];
320 lower = min(lower, coordinate);
321 upper = max(upper, coordinate);
322 }
323
324 return upper - lower;
325 }
326
332 void checkColumns_(Scalar domainHeight) const
333 {
334 using std::abs;
335 const Scalar tolerance = 1e-10*domainHeight;
336 for (const auto& element : elements(gridGeometryFine_->gridView()))
337 if (abs(elementExtent_(element.geometry(), dim - 1) - fineCellHeight_) > tolerance)
338 DUNE_THROW(Dune::InvalidStateException, "The fine grid of the VE model has to be uniform in the vertical direction");
339
340 for (std::size_t columnIdx = 0; columnIdx < columnMapping_.numberOfColumns(); ++columnIdx)
341 if (abs(columnMapping_.column(columnIdx).size()*fineCellHeight_ - domainHeight) > tolerance)
342 DUNE_THROW(Dune::InvalidStateException, "Column " << columnIdx << " does not span the domain height");
343 }
344
348 Scalar computeFineCellHeight_() const
349 {
350 const auto& gridView = gridGeometryFine_->gridView();
351 const auto element = *gridView.template begin<0>();
352 return elementExtent_(element.geometry(), dim - 1);
353 }
354
355 std::shared_ptr<const FineGridGeometry> gridGeometryFine_;
356 std::shared_ptr<const CoarseGridGeometry> gridGeometryCoarse_;
357 std::shared_ptr<const SpatialParamsFine> spatialParamsFine_;
358 QuantityReconstructor quantityReconstructor_;
359 ColumnMapping columnMapping_;
360 SolutionVector solution_;
361 FineLevelFields fineLevelFields_;
362 Scalar fineCellHeight_;
363 std::vector<TwoPVEColumnHistory<Scalar>> columnHistory_;
364};
365
366} // end namespace Dumux
367
368#endif
Implementation of the capillary pressure and relative permeability <-> saturation relations according...
Represents all relevant thermodynamic quantities of a multi-phase fluid system assuming immiscibility...
Definition immiscible.hh:30
void setTemperature(int phaseIdx, Scalar value)
Set the temperature of a fluid phase.
Definition immiscible.hh:283
void setPressure(int phaseIdx, Scalar value)
Set the fluid pressure of a phase .
Definition immiscible.hh:298
Maps horizontal coarse cells to vertically stacked fine cells using horizontal projection.
Definition columnmapping.hh:39
The quantities of a fine-level element reconstructed from the state of its coarse-level column.
Definition elementstatefine.hh:61
void update(const Element &fineElement, const TwoPVEColumnState< Scalar > &column, const SpatialParamsFine &fineSpatialParams, const QuantityReconstructor &reconstructor, const Scalar fineCellHeight)
Updates the state of a fine element.
Definition elementstatefine.hh:88
Scalar pressure(int phaseIdx) const
Returns the effective pressure of a given phase within the control volume in .
Definition elementstatefine.hh:157
Scalar saturation(int phaseIdx) const
Returns the saturation of a given phase within the control volume in .
Definition elementstatefine.hh:166
SolutionVector & solution()
Getter function for fine-level solution vector.
Definition finelevelview.hh:178
const SolutionVector & solution() const
Getter function for fine-level solution vector.
Definition finelevelview.hh:170
const ColumnMapping & columnMap() const
Getter function for mapping between coarse and fine level.
Definition finelevelview.hh:146
const QuantityReconstructor & quantityReconstructor() const
Getter function for pointer to quantity reconstructor member.
Definition finelevelview.hh:186
const SpatialParamsFine & spatialParams() const
Getter function for fine-level spatial parameters.
Definition finelevelview.hh:130
const auto & fields() const
Getter function for fine-level solution fields.
Definition finelevelview.hh:194
const FineGridGeometry & gridGeometry() const
Getter function for fine-level grid geometry.
Definition finelevelview.hh:154
ColumnState makeColumnState(const Element &coarseElement, const PrimaryVariables &coarsePriVars, const SpatialParamsCoarse &coarseSpatialParams) const
Computes and returns all quantities that define the state of a coarse-level column.
Definition finelevelview.hh:207
TwoPVEFineLevelView(std::shared_ptr< const FineGridGeometry > gridGeometry, std::shared_ptr< const CoarseGridGeometry > gridGeometryCoarse, std::shared_ptr< const SpatialParamsFine > spatialParamsFine)
Builds the mapping between the levels and checks that the grids fulfill the requirements of the model...
Definition finelevelview.hh:96
Scalar fineCellHeight() const
Returns the height of a fine-level cell (for uniform grid).
Definition finelevelview.hh:122
void updateSol(const ProblemCoarse &coarseProblem, const SolutionVector &coarseSolution)
Updates fine-level solution and solution fields given the coarse-level solution.
Definition finelevelview.hh:273
std::shared_ptr< const SpatialParamsFine > spatialParamsPtr() const
Getter function for pointer to fine-level spatial parameters.
Definition finelevelview.hh:138
TwoPVEFineLevelFieldStorage< FineGridGeometry, Scalar, FluidSystem > FineLevelFields
Definition finelevelview.hh:87
const CoarseGridGeometry & gridGeometryCoarse() const
Getter function for coarse-level grid geometry.
Definition finelevelview.hh:162
TwoPVEFineLevelElementState< FineGridGeometry, Scalar, FluidSystem > FineLevelElementState
Definition finelevelview.hh:86
Reconstructs the fine-level quantities of a column from its coarse-level quantities assuming vertical...
Definition quantityreconstruction.hh:100
Manages the maps between the coarse and fine level.
Mimics the volume variables structure of DuMux applied to the fine level of the VE scheme.
I/O container for storing fine-level quantities, used for vtk output.
@ element
Definition fieldtype.hh:23
Represents all relevant thermodynamic quantities of a multi-phase fluid system assuming immiscibility...
typename ScalarType< X >::Type Scalar
Definition odesolver.hh:52
Definition adapt.hh:17
Reconstructs quantities from the coarse to the fine level of the VE scheme.
The parameters of the Brooks-Corey material law.
Definition quantityreconstruction.hh:79
The densities of the wetting and the nonwetting phase.
Definition quantityreconstruction.hh:46
The residual saturations of the wetting and the nonwetting phase.
Definition quantityreconstruction.hh:68
The gas plume distance of a coarse-level column at the last time step and its minimum over all previo...
Definition finelevelview.hh:43
Scalar minimumGasPlumeDistance
Definition finelevelview.hh:45
Scalar gasPlumeDistance
Definition finelevelview.hh:44
The state of a coarse-level column from which the fine-level quantities are reconstructed.
Definition elementstatefine.hh:28
Scalar entryPressure
Definition elementstatefine.hh:39
Scalar minimumGasPlumeDistance
Definition elementstatefine.hh:48
Scalar domainHeight
Definition elementstatefine.hh:33
Scalar gasPlumeDistance
Definition elementstatefine.hh:47
Scalar snr
Definition elementstatefine.hh:36
Scalar swCoarse
Definition elementstatefine.hh:30
Scalar gravityNorm
Definition elementstatefine.hh:40
Scalar temperature
Definition elementstatefine.hh:31
Scalar viscosityNw
Definition elementstatefine.hh:45
Scalar brooksCoreyLambda
Definition elementstatefine.hh:38
Scalar densityW
Definition elementstatefine.hh:42
Scalar pwCoarse
Definition elementstatefine.hh:29
Scalar swr
Definition elementstatefine.hh:35
Scalar densityNw
Definition elementstatefine.hh:43
Scalar viscosityW
Definition elementstatefine.hh:44
Stores the reconstructed quantities of all fine-level elements for output.
Definition fieldstoragefine.hh:35