3.2-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
1p/sequential/diffusion/cellcentered/velocity.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3/*****************************************************************************
4 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
25#ifndef DUMUX_FVVELOCITY1P_HH
26#define DUMUX_FVVELOCITY1P_HH
27
29
30
31namespace Dumux {
47template<class TypeTag>
49{
53
55
57
60 using PrimaryVariables = typename SolutionTypes::PrimaryVariables;
62
63 using Element = typename GridView::Traits::template Codim<0>::Entity;
64 using Intersection = typename GridView::Intersection;
65
66 enum
67 {
68 dim = GridView::dimension, dimWorld = GridView::dimensionworld
69 };
70
71 enum
72 {
73 pressEqIdx = Indices::pressureEqIdx // only one equation!
74 };
75
76 using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
77 using VelocityVector = Dune::FieldVector<Scalar, dimWorld>;
78 using GravityVector = Dune::FieldVector<Scalar, dimWorld>;
79 using DimMatrix = Dune::FieldMatrix<Scalar, dim, dim>;
80
81public:
87 FVVelocity1P(Problem& problem)
88 : problem_(problem), gravity_(problem.gravity())
89 {
90 const auto element = *problem_.gridView().template begin<0>();
91 Scalar temperature = problem_.temperature(element);
92 Scalar referencePress = problem_.referencePressure(element);
93
94 density_ = FluidSystem::density(temperature, referencePress);
95 viscosity_ = FluidSystem::viscosity(temperature, referencePress);
96 }
97
98 // Calculates the velocity at a cell-cell interface.
99 void calculateVelocity(const Intersection&, CellData&);
100
101 // Calculates the velocity at a boundary.
102 void calculateVelocityOnBoundary(const Intersection&, CellData&);
103
112 template<class MultiWriter>
113 void addOutputVtkFields(MultiWriter &writer)
114 {
115 Dune::BlockVector<Dune::FieldVector<Scalar, dim> > &velocity = *(writer.template allocateManagedBuffer<Scalar, dim> (
116 problem_.gridView().size(0)));
117
118 // compute update vector
119 for (const auto& element : elements(problem_.gridView()))
120 {
121 // cell index
122 int eIdxGlobal = problem_.variables().index(element);
123
124 CellData& cellData = problem_.variables().cellData(eIdxGlobal);
125
126 const typename Element::Geometry& geometry = element.geometry();
127
128 // get corresponding reference element
129 using ReferenceElements = Dune::ReferenceElements<Scalar, dim>;
130 const auto refElement = ReferenceElements::general(geometry.type());
131
132 const int numberOfFaces = refElement.size(1);
133 std::vector<Scalar> flux(numberOfFaces,0);
134
135 // run through all intersections with neighbors and boundary
136 for (const auto& intersection : intersections(problem_.gridView(), element))
137 {
138 int isIndex = intersection.indexInInside();
139
140 flux[isIndex] = intersection.geometry().volume()
141 * (intersection.centerUnitOuterNormal() * cellData.fluxData().velocity(isIndex));
142 }
143
144 // calculate velocity on reference element as the Raviart-Thomas-0
145 // interpolant of the fluxes
146 Dune::FieldVector<Scalar, dim> refVelocity;
147 // simplices
148 if (refElement.type().isSimplex()) {
149 for (int dimIdx = 0; dimIdx < dim; dimIdx++)
150 {
151 refVelocity[dimIdx] = -flux[dim - 1 - dimIdx];
152 for (int fIdx = 0; fIdx < dim + 1; fIdx++)
153 {
154 refVelocity[dimIdx] += flux[fIdx]/(dim + 1);
155 }
156 }
157 }
158 // cubes
159 else if (refElement.type().isCube()){
160 for (int i = 0; i < dim; i++)
161 refVelocity[i] = 0.5 * (flux[2*i + 1] - flux[2*i]);
162 }
163 // 3D prism and pyramids
164 else {
165 DUNE_THROW(Dune::NotImplemented, "velocity output for prism/pyramid not implemented");
166 }
167
168 const Dune::FieldVector<Scalar, dim>& localPos
169 = refElement.position(0, 0);
170
171 // get the transposed Jacobian of the element mapping
172 const typename Element::Geometry::JacobianTransposed& jacobianT =
173 geometry.jacobianTransposed(localPos);
174
175 // calculate the element velocity by the Piola transformation
176 Dune::FieldVector<Scalar, dim> elementVelocity(0);
177 jacobianT.umtv(refVelocity, elementVelocity);
178 elementVelocity /= geometry.integrationElement(localPos);
179
180 velocity[eIdxGlobal] = elementVelocity;
181 }
182
183 writer.attachCellData(velocity, "velocity", dim);
184
185 return;
186 }
187private:
188 Problem &problem_;
189 const GravityVector& gravity_;
190 Scalar density_;
191 Scalar viscosity_;
192};
193
203template<class TypeTag>
204void FVVelocity1P<TypeTag>::calculateVelocity(const Intersection& intersection, CellData& cellData)
205{
206 auto elementI = intersection.inside();
207 auto elementJ = intersection.outside();
208
209 int eIdxGlobalJ = problem_.variables().index(elementJ);
210
211 CellData& cellDataJ = problem_.variables().cellData(eIdxGlobalJ);
212
213 // get global coordinates of cell centers
214 const GlobalPosition& globalPosI = elementI.geometry().center();
215 const GlobalPosition& globalPosJ = elementJ.geometry().center();
216
217 //get face index
218 int isIndexI = intersection.indexInInside();
219 int isIndexJ = intersection.indexInOutside();
220
221 //get face normal
222 const Dune::FieldVector<Scalar, dim>& unitOuterNormal = intersection.centerUnitOuterNormal();
223
224 // distance vector between barycenters
225 GlobalPosition distVec = globalPosJ - globalPosI;
226
227 // compute distance between cell centers
228 Scalar dist = distVec.two_norm();
229
230 // compute vectorized permeabilities
231 DimMatrix meanPermeability(0);
232
233 problem_.spatialParams().meanK(meanPermeability, problem_.spatialParams().intrinsicPermeability(elementI),
234 problem_.spatialParams().intrinsicPermeability(elementJ));
235
236 Dune::FieldVector < Scalar, dim > permeability(0);
237 meanPermeability.mv(unitOuterNormal, permeability);
238
239 permeability /= viscosity_;
240
241 // calculate potential gradients
242 Scalar potential = (cellData.pressure() - cellDataJ.pressure()) / dist;
243
244 potential += density_ * (unitOuterNormal * gravity_);
245
246 // store potentials for further calculations (velocity, saturation, ...)
247 cellData.fluxData().setPotential(isIndexI, potential);
248 cellDataJ.fluxData().setPotential(isIndexJ, -potential);
249
250 // calculate the gravity term
251 VelocityVector velocity(permeability);
252 velocity *= (cellData.pressure() - cellDataJ.pressure()) / dist;
253
254 GravityVector gravityTerm(unitOuterNormal);
255 gravityTerm *= (gravity_ * permeability) * density_;
256
257 velocity += gravityTerm;
258
259 // store velocities
260 cellData.fluxData().setVelocity(isIndexI, velocity);
261 cellData.fluxData().setVelocityMarker(isIndexI);
262
263 cellDataJ.fluxData().setVelocity(isIndexJ, velocity);
264 cellDataJ.fluxData().setVelocityMarker(isIndexJ);
265 return;
266}
267
277template<class TypeTag>
278void FVVelocity1P<TypeTag>::calculateVelocityOnBoundary(const Intersection& intersection, CellData& cellData)
279{
280 auto element = intersection.inside();
281
282 // get face index
283 int isIndex = intersection.indexInInside();
284
285 // get face normal
286 const Dune::FieldVector<Scalar, dim>& unitOuterNormal = intersection.centerUnitOuterNormal();
287
288 BoundaryTypes bcType;
289 // get boundary type
290 problem_.boundaryTypes(bcType, intersection);
291 PrimaryVariables boundValues(0.0);
292
293 if (bcType.isDirichlet(pressEqIdx))
294 {
295 problem_.dirichlet(boundValues, intersection);
296
297 // get global coordinates of cell centers
298 const GlobalPosition& globalPosI = element.geometry().center();
299
300 // center of face in global coordinates
301 const GlobalPosition& globalPosJ = intersection.geometry().center();
302
303 // distance vector between barycenters
304 GlobalPosition distVec = globalPosJ - globalPosI;
305
306 // compute distance between cell centers
307 Scalar dist = distVec.two_norm();
308
309 // permeability vector at boundary
310 // compute vectorized permeabilities
311 DimMatrix meanPermeability(0);
312
313 problem_.spatialParams().meanK(meanPermeability, problem_.spatialParams().intrinsicPermeability(element));
314
315 // multiply with normal vector at the boundary
316 Dune::FieldVector < Scalar, dim > permeability(0);
317 meanPermeability.mv(unitOuterNormal, permeability);
318 permeability /= viscosity_;
319
320 Scalar pressBound = boundValues;
321
322 // calculate potential gradients
323 Scalar potential = (cellData.pressure() - pressBound) / dist;
324
325 potential += density_ * (unitOuterNormal * gravity_);
326
327 // store potentials for further calculations (velocity, saturation, ...)
328 cellData.fluxData().setPotential(isIndex, potential);
329
330 // calculate the gravity term
331 VelocityVector velocity(permeability);
332 velocity *= (cellData.pressure() - pressBound) / dist;
333
334 GravityVector gravityTerm(unitOuterNormal);
335 gravityTerm *= (gravity_ * permeability) * density_;
336
337 velocity += gravityTerm;
338
339 // store velocities
340 cellData.fluxData().setVelocity(isIndex, velocity);
341 cellData.fluxData().setVelocityMarker(isIndex);
342
343 } // end Dirichlet boundary
344
345 else
346 {
347 problem_.neumann(boundValues, intersection);
348 VelocityVector velocity(unitOuterNormal);
349
350 velocity *= boundValues[pressEqIdx] / density_;
351
352 // store potential gradients for further calculations
353 cellData.fluxData().setPotential(isIndex, boundValues[pressEqIdx]);
354
355 //store velocity
356 cellData.fluxData().setVelocity(isIndex, velocity);
357 cellData.fluxData().setVelocityMarker(isIndex);
358 } // end Neumann boundary
359 return;
360}
361} // end namespace Dumux
362#endif
void calculateVelocityOnBoundary(const Intersection &, CellData &)
Calculates the velocity at a boundary.
Definition: 1p/sequential/diffusion/cellcentered/velocity.hh:278
void calculateVelocity(const Intersection &, CellData &)
Calculates the velocity at a cell-cell interface.
Definition: 1p/sequential/diffusion/cellcentered/velocity.hh:204
Definition: adapt.hh:29
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type GetProp
get the type of a property (equivalent to old macro GET_PROP(...))
Definition: propertysystem.hh:140
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:149
std::string temperature() noexcept
I/O name of temperature for equilibrium models.
Definition: name.hh:51
std::string viscosity(int phaseIdx) noexcept
I/O name of viscosity for multiphase systems.
Definition: name.hh:74
std::string permeability() noexcept
I/O name of permeability.
Definition: name.hh:143
std::string density(int phaseIdx) noexcept
I/O name of density for multiphase systems.
Definition: name.hh:65
Single phase finite volume velocity reconstruction.
Definition: 1p/sequential/diffusion/cellcentered/velocity.hh:49
FVVelocity1P(Problem &problem)
Constructs a FVVelocity1P object.
Definition: 1p/sequential/diffusion/cellcentered/velocity.hh:87
void addOutputVtkFields(MultiWriter &writer)
Adds velocity output to the output file.
Definition: 1p/sequential/diffusion/cellcentered/velocity.hh:113
Defines the properties required for the single phase sequential model.