3.6-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
freeflow/rans/problem.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3/*****************************************************************************
4 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
24#ifndef DUMUX_RANS_PROBLEM_HH
25#define DUMUX_RANS_PROBLEM_HH
26
27#include <algorithm>
28
29#include <dune/common/fmatrix.hh>
37#include "model.hh"
38
39namespace Dumux {
40
42template<class TypeTag, TurbulenceModel turbulenceModel>
44
46template<class TypeTag>
48
57template<class TypeTag>
59{
61 using Implementation = GetPropType<TypeTag, Properties::Problem>;
62
64
66 using FVElementGeometry = typename GridGeometry::LocalView;
67 using GridView = typename GridGeometry::GridView;
68 using Element = typename GridView::template Codim<0>::Entity;
69 using SubControlVolume = typename FVElementGeometry::SubControlVolume;
70 using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace;
72 using PrimaryVariables = typename VolumeVariables::PrimaryVariables;
73 using CellCenterPrimaryVariables = GetPropType<TypeTag, Properties::CellCenterPrimaryVariables>;
76
77 using GlobalPosition = typename SubControlVolumeFace::GlobalPosition;
78
79 static constexpr auto dim = GridView::dimension;
80 static constexpr int numCorners = SubControlVolumeFace::numCornersPerFace;
81 using DimVector = GlobalPosition;
82 using DimMatrix = Dune::FieldMatrix<Scalar, dim, dim>;
83
84 struct WallElementInformation
85 {
86 // store the element indices for all elements with an intersection on the wall
87 unsigned int wallElementIdx;
88 // for each wall element, store the faces normal axis
89 unsigned int wallFaceNormalAxis;
90 // for each wall element, store the location of the face center and each corner.
91 GlobalPosition wallFaceCenter;
92 std::array<GlobalPosition, numCorners> wallFaceCorners;
93 };
94
95public:
96
102 RANSProblemBase(std::shared_ptr<const GridGeometry> gridGeometry, const std::string& paramGroup = "")
104 {
105 if ( !(hasParamInGroup(this->paramGroup(), "RANS.IsFlatWallBounded")))
106 {
107 std::cout << "The parameter \"Rans.IsFlatWallBounded\" is not specified. \n"
108 << " -- Based on the grid and the boundary conditions specified by the user,"
109 << " this parameter is set to be "<< std::boolalpha << isFlatWallBounded() << "\n";
110 }
111
112 // update size and initial values of the global vectors
113 wallDistance_.resize(this->gridGeometry().elementMapper().size(), std::numeric_limits<Scalar>::max());
114 neighborIdx_.resize(this->gridGeometry().elementMapper().size());
115 velocity_.resize(this->gridGeometry().elementMapper().size(), DimVector(0.0));
116 velocityGradients_.resize(this->gridGeometry().elementMapper().size(), DimMatrix(0.0));
117 stressTensorScalarProduct_.resize(this->gridGeometry().elementMapper().size(), 0.0);
118 vorticityTensorScalarProduct_.resize(this->gridGeometry().elementMapper().size(), 0.0);
119 flowDirectionAxis_.resize(this->gridGeometry().elementMapper().size(), fixedFlowDirectionAxis_);
120 storedViscosity_.resize(this->gridGeometry().elementMapper().size(), 0.0);
121 storedDensity_.resize(this->gridGeometry().elementMapper().size(), 0.0);
122 }
123
128 {
129 std::cout << "Update static wall properties. ";
131
132 checkForWalls_();
133 findWallDistances_();
134 findNeighborIndices_();
135 }
136
142 template<class SolutionVector>
143 void updateDynamicWallProperties(const SolutionVector& curSol)
144 {
145 std::cout << "Update dynamic wall properties." << std::endl;
147 DUNE_THROW(Dune::InvalidStateException,
148 "You have to call updateStaticWallProperties() once before you call updateDynamicWallProperties().");
149
150 calculateCCVelocities_(curSol);
151 calculateCCVelocityGradients_();
152 calculateMaxMinVelocities_();
153 calculateStressTensor_();
154 calculateVorticityTensor_();
155 storeViscosities_(curSol);
156 }
157
165 bool useWallFunction(const Element& element,
166 const SubControlVolumeFace& scvf,
167 const int& eqIdx) const
168 { return false; }
169
173 template<class ElementVolumeVariables, class ElementFaceVariables>
174 FacePrimaryVariables wallFunction(const Element& element,
175 const FVElementGeometry& fvGeometry,
176 const ElementVolumeVariables& elemVolVars,
177 const ElementFaceVariables& elemFaceVars,
178 const SubControlVolumeFace& scvf,
179 const SubControlVolumeFace& lateralBoundaryFace) const
180 { return FacePrimaryVariables(0.0); }
181
185 template<class ElementVolumeVariables, class ElementFaceVariables>
186 CellCenterPrimaryVariables wallFunction(const Element& element,
187 const FVElementGeometry& fvGeometry,
188 const ElementVolumeVariables& elemVolVars,
189 const ElementFaceVariables& elemFaceVars,
190 const SubControlVolumeFace& scvf) const
191 { return CellCenterPrimaryVariables(0.0); }
192
198 bool isFlatWallBounded() const
199 {
200 static const bool hasAlignedWalls = hasAlignedWalls_();
201 return hasAlignedWalls;
202 }
203
207 const Scalar karmanConstant() const
208 { return 0.41; }
209
211 const Scalar betaOmega() const
212 { return 0.0708; }
213
219 {
220 static const Scalar turbulentPrandtlNumber
221 = getParamFromGroup<Scalar>(this->paramGroup(), "RANS.TurbulentPrandtlNumber", 1.0);
223 }
224
230 {
231 static const Scalar turbulentSchmidtNumber
232 = getParamFromGroup<Scalar>(this->paramGroup(), "RANS.TurbulentSchmidtNumber", 1.0);
234 }
235
236 int wallNormalAxis(const int elementIdx) const
237 {
238 if (!isFlatWallBounded())
239 DUNE_THROW(Dune::NotImplemented, "\n Due to grid/geometric concerns, models requiring a wallNormalAxis "
240 << "can only be used for flat wall bounded flows. "
241 << "\n If your geometry is a flat channel, "
242 << "please set the runtime parameter RANS.IsFlatWallBounded to true. \n");
243 return wallNormalAxis_[elementIdx];
244 }
245
246 int flowDirectionAxis(const int elementIdx) const
247 {
248 if (!isFlatWallBounded())
249 DUNE_THROW(Dune::NotImplemented, "\n Due to grid/geometric concerns, models requiring a flowDirectionAxis "
250 << "can only be used for flat wall bounded flows. "
251 << "\n If your geometry is a flat channel, "
252 << "please set the runtime parameter RANS.IsFlatWallBounded to true. \n");
253 return flowDirectionAxis_[elementIdx];
254 }
255
256 unsigned int wallElementIndex(const int elementIdx) const
257 {
258 if (!isFlatWallBounded())
259 DUNE_THROW(Dune::NotImplemented, "\n Due to grid/geometric concerns, models requiring a wallElementIndex "
260 << "can only be used for flat wall bounded flows. "
261 << "\n If your geometry is a flat channel, "
262 << "please set the runtime parameter RANS.IsFlatWallBounded to true. \n");
263 return wallElementIdx_[elementIdx];
264
265 }
266
267 Scalar wallDistance(const int elementIdx) const
268 { return wallDistance_[elementIdx]; }
269
270 GlobalPosition cellCenter(const int elementIdx) const
271 {
272 const auto& element = this->gridGeometry().element(elementIdx);
273 return element.geometry().center();
274 }
275
276 unsigned int neighborIndex(const int elementIdx, const int axisIdx, const int sideIdx) const
277 { return neighborIdx_[elementIdx][axisIdx][sideIdx];}
278
279 DimVector ccVelocityVector(const int elementIdx) const
280 { return velocity_[elementIdx]; }
281
282 Scalar ccVelocity(const int elementIdx, const int axisIdx) const
283 { return velocity_[elementIdx][axisIdx]; }
284
285 DimVector velocityMaximum(const int elementIdx) const
286 { return velocityMaximum_[elementIdx]; }
287
288 DimVector velocityMinimum(const int elementIdx) const
289 { return velocityMinimum_[elementIdx]; }
290
291 DimMatrix velocityGradientTensor(const int elementIdx) const
292 { return velocityGradients_[elementIdx]; }
293
294 Scalar velocityGradient(const int elementIdx, const int i, const int j) const
295 { return velocityGradients_[elementIdx][i][j]; }
296
297 Scalar stressTensorScalarProduct(const int elementIdx) const
298 { return stressTensorScalarProduct_[elementIdx]; }
299
300 Scalar vorticityTensorScalarProduct(const int elementIdx) const
301 { return vorticityTensorScalarProduct_[elementIdx]; }
302
303 Scalar storedViscosity(const int elementIdx) const
304 { return storedViscosity_[elementIdx]; }
305
306 Scalar storedDensity(const int elementIdx) const
307 { return storedDensity_[elementIdx]; }
308
309 Scalar kinematicViscosity(const int elementIdx) const
310 { return storedViscosity(elementIdx) / storedDensity(elementIdx); }
311
313
314private:
315
316 bool hasAlignedWalls_() const
317 {
318 if ( hasParamInGroup(this->paramGroup(), "RANS.IsFlatWallBounded"))
319 {
320 static const bool isFlatWallBounded = getParamFromGroup<bool>(this->paramGroup(), "RANS.IsFlatWallBounded");
321 return isFlatWallBounded;
322 }
323
324 std::vector<int> wallFaceAxis;
325 wallFaceAxis.reserve(this->gridGeometry().numBoundaryScvf());
326
327 const auto gridView = this->gridGeometry().gridView();
328 auto fvGeometry = localView(this->gridGeometry());
329 for (const auto& element : elements(gridView))
330 {
331 fvGeometry.bindElement(element);
332 for (const auto& scvf : scvfs(fvGeometry))
333 if (!scvf.boundary() && asImp_().boundaryTypes(element, scvf).hasWall()) // only search for walls at a global boundary
334 wallFaceAxis.push_back(scvf.directionIndex());
335 }
336
337 // Returns if all wall directions are the same
338 return std::all_of(wallFaceAxis.begin(), wallFaceAxis.end(), [firstDir=wallFaceAxis[0]](auto dir){ return (dir == firstDir);} ) ;
339 }
340
341 void checkForWalls_()
342 {
343 for (const auto& element : elements(this->gridGeometry().gridView()))
344 {
345 auto fvGeometry = localView(this->gridGeometry());
346 fvGeometry.bindElement(element);
347 for (auto&& scvf : scvfs(fvGeometry))
348 if (asImp_().boundaryTypes(element, scvf).hasWall())
349 return;
350 }
351 // If reached, no walls were found using the boundary types has wall function.
352 DUNE_THROW(Dune::InvalidStateException, "No walls are are specified with the setWall() function");
353 }
354
360 void findWallDistances_()
361 {
362 WallDistance wallInformation(this->gridGeometry(), WallDistance<GridGeometry>::atElementCenters,
363 [this] (const FVElementGeometry& fvGeometry, const SubControlVolumeFace& scvf)
364 { return asImp_().boundaryTypes(fvGeometry.element(), scvf).hasWall(); });
365 wallDistance_ = wallInformation.wallDistance();
366 storeWallElementAndDirectionIndex_(wallInformation.wallData());
367 }
368
369 template <class WallData>
370 void storeWallElementAndDirectionIndex_(const WallData& wallData)
371 {
372 // The wall Direction Index is used for flat quadrilateral channel problems only
373 if (!(GridGeometry::discMethod == DiscretizationMethods::staggered))
374 DUNE_THROW(Dune::NotImplemented, "The wall direction Index can only be calculated for quadrilateral structured grids");
375
376 // If isFlatWallBounded, the corresponding wall element is stored for each element
377 if (isFlatWallBounded())
378 {
379 wallNormalAxis_.resize(wallData.size());
380 wallElementIdx_.resize(wallData.size());
381
382 for (const auto& element : elements(this->gridGeometry().gridView()))
383 {
384 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
385 wallElementIdx_[elementIdx] = wallData[elementIdx].eIdx;
386 if ( ! (hasParam("RANS.WallNormalAxis")) )
387 {
388 GlobalPosition wallOuterNormal = wallData[elementIdx].scvfOuterNormal;
389 if constexpr (dim == 2) // 2D
390 wallNormalAxis_[elementIdx] = (wallOuterNormal[0] == 1) ? 0 : 1;
391 else // 3D
392 wallNormalAxis_[elementIdx] = (wallOuterNormal[0] == 1) ? 0 : ((wallOuterNormal[1] == 1) ? 1 : 2);
393 }
394 else
395 wallNormalAxis_[elementIdx] = fixedWallNormalAxis_;
396 }
397 }
398 }
399
403 void findNeighborIndices_()
404 {
405 // search for neighbor Idxs
406 for (const auto& element : elements(this->gridGeometry().gridView()))
407 {
408 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
409 for (unsigned int axisIdx = 0; axisIdx < dim; ++axisIdx)
410 {
411 neighborIdx_[elementIdx][axisIdx][0] = elementIdx;
412 neighborIdx_[elementIdx][axisIdx][1] = elementIdx;
413 }
414
415 for (const auto& intersection : intersections(this->gridGeometry().gridView(), element))
416 {
417 if (intersection.boundary())
418 continue;
419
420 unsigned int neighborIdx = this->gridGeometry().elementMapper().index(intersection.outside());
421 for (unsigned int axisIdx = 0; axisIdx < dim; ++axisIdx)
422 {
423 if (abs(cellCenter(elementIdx)[axisIdx] - cellCenter(neighborIdx)[axisIdx]) > 1e-8)
424 {
425 if (cellCenter(elementIdx)[axisIdx] > cellCenter(neighborIdx)[axisIdx])
426 neighborIdx_[elementIdx][axisIdx][0] = neighborIdx;
427
428 if (cellCenter(elementIdx)[axisIdx] < cellCenter(neighborIdx)[axisIdx])
429 neighborIdx_[elementIdx][axisIdx][1] = neighborIdx;
430 }
431 }
432 }
433 }
434 }
435
436 template<class SolutionVector>
437 void calculateCCVelocities_(const SolutionVector& curSol)
438 {
439 auto fvGeometry = localView(this->gridGeometry());
440 // calculate cell-center-averaged velocities
441 for (const auto& element : elements(this->gridGeometry().gridView()))
442 {
443 fvGeometry.bindElement(element);
444 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
445
446 // calculate velocities
447 DimVector velocityTemp(0.0);
448 for (auto&& scvf : scvfs(fvGeometry))
449 {
450 const int dofIdxFace = scvf.dofIndex();
451 const auto numericalSolutionFace = curSol[GridGeometry::faceIdx()][dofIdxFace][Indices::velocity(scvf.directionIndex())];
452 velocityTemp[scvf.directionIndex()] += numericalSolutionFace;
453 }
454 for (unsigned int axisIdx = 0; axisIdx < dim; ++axisIdx)
455 velocity_[elementIdx][axisIdx] = velocityTemp[axisIdx] * 0.5; // faces are equidistant to cell center
456 }
457 }
458
459
460 void calculateCCVelocityGradients_()
461 {
462 using std::abs;
463
464 // calculate cell-center-averaged velocity gradients, maximum, and minimum values
465 auto fvGeometry = localView(this->gridGeometry());
466 for (const auto& element : elements(this->gridGeometry().gridView()))
467 {
468 const unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
469
470 for (unsigned int j = 0; j < dim; ++j)
471 {
472 for (unsigned int i = 0; i < dim; ++i)
473 {
474 const unsigned int neighborIndex0 = neighborIndex(elementIdx, j, 0);
475 const unsigned int neighborIndex1 = neighborIndex(elementIdx, j, 1);
476
477 velocityGradients_[elementIdx][i][j]
478 = (ccVelocity(neighborIndex1, i) - ccVelocity(neighborIndex0, i))
479 / (cellCenter(neighborIndex1)[j] - cellCenter(neighborIndex0)[j]);
480
481 if (abs(cellCenter(neighborIndex1)[j] - cellCenter(neighborIndex0)[j]) < 1e-8)
482 velocityGradients_[elementIdx][i][j] = 0.0;
483 }
484 }
485
486 fvGeometry.bindElement(element);
487 for (auto&& scvf : scvfs(fvGeometry))
488 {
489 // adapt calculations for Dirichlet condition
490 unsigned int axisIdx = scvf.directionIndex();
491 if (scvf.boundary())
492 {
493 for (unsigned int velIdx = 0; velIdx < dim; ++velIdx)
494 {
495 if (!asImp_().boundaryTypes(element, scvf).isDirichlet(Indices::velocity(velIdx)))
496 continue;
497
498 Scalar dirichletVelocity = asImp_().dirichlet(element, scvf)[Indices::velocity(velIdx)];
499
500 unsigned int neighborIdx = neighborIndex(elementIdx, axisIdx, 0);
501 if (scvf.center()[axisIdx] < cellCenter(elementIdx)[axisIdx])
502 neighborIdx = neighborIndex(elementIdx, axisIdx, 1);
503
504 velocityGradients_[elementIdx][velIdx][axisIdx]
505 = (ccVelocity(neighborIdx, velIdx) - dirichletVelocity)
506 / (cellCenter(neighborIdx)[axisIdx] - scvf.center()[axisIdx]);
507 }
508 }
509
510 // Calculate the BJS-velocity by accounting for all sub faces.
511 std::vector<int> bjsNumFaces(dim, 0);
512 std::vector<unsigned int> bjsNeighbor(dim, 0);
513 DimVector bjsVelocityAverage(0.0);
514 DimVector normalNormCoordinate(0.0);
515 unsigned int velCompIdx = Indices::velocity(scvf.directionIndex());
516 const int numSubFaces = scvf.pairData().size();
517 for(int localSubFaceIdx = 0; localSubFaceIdx < numSubFaces; ++localSubFaceIdx)
518 {
519 const auto& lateralFace = fvGeometry.scvf(scvf.insideScvIdx(), scvf.pairData()[localSubFaceIdx].localLateralFaceIdx);
520
521 // adapt calculations for Beavers-Joseph-Saffman condition
522 unsigned int lateralAxisIdx = lateralFace.directionIndex();
523 if (lateralFace.boundary() && (asImp_().boundaryTypes(element, lateralFace).isBeaversJoseph(Indices::velocity(velCompIdx))))
524 {
525 unsigned int neighborIdx = neighborIndex(elementIdx, lateralAxisIdx, 0);
526 if (lateralFace.center()[lateralAxisIdx] < cellCenter(elementIdx)[lateralAxisIdx])
527 neighborIdx = neighborIndex(elementIdx, lateralAxisIdx, 1);
528
529 const SubControlVolume& scv = fvGeometry.scv(scvf.insideScvIdx());
530 bjsVelocityAverage[lateralAxisIdx] += ParentType::beaversJosephVelocity(element, scv, scvf, lateralFace, ccVelocity(elementIdx, velCompIdx), 0.0);
531 if (bjsNumFaces[lateralAxisIdx] > 0 && neighborIdx != bjsNeighbor[lateralAxisIdx])
532 DUNE_THROW(Dune::InvalidStateException, "Two different neighborIdx should not occur");
533 bjsNeighbor[lateralAxisIdx] = neighborIdx;
534 normalNormCoordinate[lateralAxisIdx] = lateralFace.center()[lateralAxisIdx];
535 bjsNumFaces[lateralAxisIdx]++;
536 }
537 }
538 for (unsigned axisIdx = 0; axisIdx < dim; ++axisIdx)
539 {
540 if (bjsNumFaces[axisIdx] == 0)
541 continue;
542
543 unsigned int neighborIdx = bjsNeighbor[axisIdx];
544 bjsVelocityAverage[axisIdx] /= bjsNumFaces[axisIdx];
545
546 velocityGradients_[elementIdx][velCompIdx][axisIdx]
547 = (ccVelocity(neighborIdx, velCompIdx) - bjsVelocityAverage[axisIdx])
548 / (cellCenter(neighborIdx)[axisIdx] - normalNormCoordinate[axisIdx]);
549 }
550 }
551 }
552 }
553
554 void calculateMaxMinVelocities_()
555 {
556 using std::abs;
557 if (isFlatWallBounded())
558 {
559 // If the parameter isFlatWallBounded is set to true,
560 // the maximum/minimum velocities are calculated along a profile perpendicular to the corresponding wall face.
561
562 // re-initialize min and max values
563 velocityMaximum_.assign(this->gridGeometry().elementMapper().size(), DimVector(1e-16));
564 velocityMinimum_.assign(this->gridGeometry().elementMapper().size(), DimVector(std::numeric_limits<Scalar>::max()));
565
566 // For each profile perpendicular to the channel wall, find the max and minimum velocities
567 for (const auto& element : elements(this->gridGeometry().gridView()))
568 {
569 const unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
570 Scalar maxVelocity = 0.0;
571 const unsigned int wallElementIdx = wallElementIndex(elementIdx);
572
573 for (unsigned int axisIdx = 0; axisIdx < dim; ++axisIdx)
574 {
575 if (abs(ccVelocity(elementIdx, axisIdx)) > abs(velocityMaximum_[wallElementIdx][axisIdx]))
576 velocityMaximum_[wallElementIdx][axisIdx] = ccVelocity(elementIdx, axisIdx);
577
578 if (abs(ccVelocity(elementIdx, axisIdx)) < abs(velocityMinimum_[wallElementIdx][axisIdx]))
579 velocityMinimum_[wallElementIdx][axisIdx] = ccVelocity(elementIdx, axisIdx);
580
581 // Set the flow direction axis as the direction of the max velocity
582 if ((hasParam("RANS.FlowDirectionAxis") != 1) && (maxVelocity) < abs(ccVelocity(elementIdx, axisIdx)))
583 {
584 maxVelocity = abs(ccVelocity(elementIdx, axisIdx));
585 flowDirectionAxis_[elementIdx] = axisIdx;
586 }
587 }
588 }
589 }
590 else
591 {
592 // If the parameter isFlatWallBounded is set to false, or not set,
593 // the maximum/minimum velocities are calculated as a global max/min throughout the domain.
594
595 DimVector maxVelocity(0.0);
596 DimVector minVelocity(std::numeric_limits<Scalar>::max());
597 // Find the max and minimum velocities in the full domain
598 for (const auto& element : elements(this->gridGeometry().gridView()))
599 {
600 const unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
601
602 for (unsigned int axisIdx = 0; axisIdx < dim; ++axisIdx)
603 {
604 if (abs(ccVelocity(elementIdx, axisIdx)) > abs(maxVelocity[axisIdx]))
605 maxVelocity[axisIdx] = ccVelocity(elementIdx, axisIdx);
606
607 if (abs(ccVelocity(elementIdx, axisIdx)) < abs(minVelocity[axisIdx]))
608 minVelocity[axisIdx] = ccVelocity(elementIdx, axisIdx);
609 }
610 }
611 velocityMaximum_.assign(this->gridGeometry().elementMapper().size(), maxVelocity);
612 velocityMinimum_.assign(this->gridGeometry().elementMapper().size(), minVelocity);
613 }
614 }
615
616 void calculateStressTensor_()
617 {
618 for (const auto& element : elements(this->gridGeometry().gridView()))
619 {
620 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
621 Dune::FieldMatrix<Scalar, GridView::dimension, GridView::dimension> stressTensor(0.0);
622 for (unsigned int j = 0; j < dim; ++j)
623 {
624 for (unsigned int i = 0; i < dim; ++i)
625 {
626 stressTensor[j][i] = 0.5 * velocityGradient(elementIdx, j, i)
627 + 0.5 * velocityGradient(elementIdx, i, j);
628 }
629 }
630 stressTensorScalarProduct_[elementIdx] = 0.0;
631 for (unsigned int j = 0; j < dim; ++j)
632 {
633 for (unsigned int i = 0; i < dim; ++i)
634 {
635 stressTensorScalarProduct_[elementIdx] += stressTensor[j][i] * stressTensor[j][i];
636 }
637 }
638 }
639 }
640
641 void calculateVorticityTensor_()
642 {
643 for (const auto& element : elements(this->gridGeometry().gridView()))
644 {
645 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
646 Dune::FieldMatrix<Scalar, GridView::dimension, GridView::dimension> vorticityTensor(0.0);
647 for (unsigned int j = 0; j < dim; ++j)
648 {
649 for (unsigned int i = 0; i < dim; ++i)
650 {
651 vorticityTensor[j][i] = 0.5 * velocityGradient(elementIdx, j, i)
652 - 0.5 * velocityGradient(elementIdx, i, j);
653 }
654 }
655 vorticityTensorScalarProduct_[elementIdx] = 0.0;
656 for (unsigned int j = 0; j < dim; ++j)
657 {
658 for (unsigned int i = 0; i < dim; ++i)
659 {
660 vorticityTensorScalarProduct_[elementIdx] += vorticityTensor[j][i] * vorticityTensor[j][i];
661 }
662 }
663 }
664 }
665
666 template<class SolutionVector>
667 void storeViscosities_(const SolutionVector& curSol)
668 {
669 // calculate or call all secondary variables
670 auto fvGeometry = localView(this->gridGeometry());
671 for (const auto& element : elements(this->gridGeometry().gridView()))
672 {
673 unsigned int elementIdx = this->gridGeometry().elementMapper().index(element);
674 fvGeometry.bindElement(element);
675 for (auto&& scv : scvs(fvGeometry))
676 {
677 const int dofIdx = scv.dofIndex();
678 // construct a privars object from the cell center solution vector
679 const auto& cellCenterPriVars = curSol[GridGeometry::cellCenterIdx()][dofIdx];
680 PrimaryVariables priVars = makePriVarsFromCellCenterPriVars<PrimaryVariables>(cellCenterPriVars);
681 auto elemSol = elementSolution<typename GridGeometry::LocalView>(std::move(priVars));
682
683 VolumeVariables volVars;
684 volVars.update(elemSol, asImp_(), element, scv);
685 storedDensity_[elementIdx] = volVars.density();
686 storedViscosity_[elementIdx] = volVars.viscosity();
687 }
688 }
689 }
690
691 const int fixedFlowDirectionAxis_ = getParam<int>("RANS.FlowDirectionAxis", 0);
692 const int fixedWallNormalAxis_ = getParam<int>("RANS.WallNormalAxis", 1);
693
694 std::vector<unsigned int> wallNormalAxis_;
695 std::vector<unsigned int> flowDirectionAxis_;
696 std::vector<Scalar> wallDistance_;
697 std::vector<unsigned int> wallElementIdx_;
698 std::vector<std::array<std::array<unsigned int, 2>, dim>> neighborIdx_;
699
700 std::vector<DimVector> velocity_;
701 std::vector<DimVector> velocityMaximum_;
702 std::vector<DimVector> velocityMinimum_;
703 std::vector<DimMatrix> velocityGradients_;
704
705 std::vector<Scalar> stressTensorScalarProduct_;
706 std::vector<Scalar> vorticityTensorScalarProduct_;
707
708 std::vector<Scalar> storedDensity_;
709 std::vector<Scalar> storedViscosity_;
710
712 Implementation &asImp_()
713 { return *static_cast<Implementation *>(this); }
714
716 const Implementation &asImp_() const
717 { return *static_cast<const Implementation *>(this); }
718};
719
720} // end namespace Dumux
721
722#endif
Base class for all staggered fv problems.
Free function to get the local view of a grid cache object.
The available discretization methods in Dumux.
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition: localview.hh:38
bool hasParamInGroup(const std::string &paramGroup, const std::string &param)
Check whether a key exists in the parameter tree with a model group prefix.
Definition: parameters.hh:177
bool hasParam(const std::string &param)
Check whether a key exists in the parameter tree.
Definition: parameters.hh:169
Adaption of the non-isothermal two-phase two-component flow model to problems with CO2.
Definition: adapt.hh:29
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:180
constexpr Staggered staggered
Definition: method.hh:138
Base class for all finite-volume problems.
Definition: common/fvproblem.hh:55
const std::string & paramGroup() const
The parameter group in which to retrieve runtime parameters.
Definition: common/fvproblem.hh:544
const GridGeometry & gridGeometry() const
The finite volume grid geometry.
Definition: common/fvproblem.hh:540
auto boundaryTypes(const Element &element, const SubControlVolume &scv) const
Specifies which kind of boundary condition should be used for which equation on a given boundary segm...
Definition: common/fvproblem.hh:143
static constexpr auto atElementCenters
Definition: walldistance.hh:110
Navier-Stokes staggered problem base class.
Definition: freeflow/navierstokes/staggered/problem.hh:45
const Scalar beaversJosephVelocity(const Element &element, const SubControlVolume &scv, const SubControlVolumeFace &ownScvf, const SubControlVolumeFace &faceOnPorousBoundary, const Scalar velocitySelf, const Scalar tangentialVelocityGradient) const
Returns the slip velocity at a porous boundary based on the Beavers-Joseph(-Saffman) condition.
Definition: freeflow/navierstokes/staggered/problem.hh:201
forward declare
Definition: freeflow/rans/problem.hh:43
Reynolds-Averaged Navier-Stokes problem base class.
Definition: freeflow/rans/problem.hh:59
unsigned int wallElementIndex(const int elementIdx) const
Definition: freeflow/rans/problem.hh:256
int flowDirectionAxis(const int elementIdx) const
Definition: freeflow/rans/problem.hh:246
void updateDynamicWallProperties(const SolutionVector &curSol)
Update the dynamic (solution dependent) turbulence parameters.
Definition: freeflow/rans/problem.hh:143
DimMatrix velocityGradientTensor(const int elementIdx) const
Definition: freeflow/rans/problem.hh:291
Scalar vorticityTensorScalarProduct(const int elementIdx) const
Definition: freeflow/rans/problem.hh:300
Scalar ccVelocity(const int elementIdx, const int axisIdx) const
Definition: freeflow/rans/problem.hh:282
void updateStaticWallProperties()
Update the static (solution independent) relations to the walls and neighbors.
Definition: freeflow/rans/problem.hh:127
GlobalPosition cellCenter(const int elementIdx) const
Definition: freeflow/rans/problem.hh:270
FacePrimaryVariables wallFunction(const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &elemVolVars, const ElementFaceVariables &elemFaceVars, const SubControlVolumeFace &scvf, const SubControlVolumeFace &lateralBoundaryFace) const
Returns an additional wall function momentum flux.
Definition: freeflow/rans/problem.hh:174
Scalar velocityGradient(const int elementIdx, const int i, const int j) const
Definition: freeflow/rans/problem.hh:294
DimVector velocityMaximum(const int elementIdx) const
Definition: freeflow/rans/problem.hh:285
const Scalar betaOmega() const
Returns the constant.
Definition: freeflow/rans/problem.hh:211
DimVector ccVelocityVector(const int elementIdx) const
Definition: freeflow/rans/problem.hh:279
Scalar kinematicViscosity(const int elementIdx) const
Definition: freeflow/rans/problem.hh:309
Scalar turbulentSchmidtNumber() const
Return the turbulent Schmidt number which is used to convert the eddy viscosity to an eddy diffusivi...
Definition: freeflow/rans/problem.hh:229
CellCenterPrimaryVariables wallFunction(const Element &element, const FVElementGeometry &fvGeometry, const ElementVolumeVariables &elemVolVars, const ElementFaceVariables &elemFaceVars, const SubControlVolumeFace &scvf) const
Returns an additional wall function flux for cell-centered quantities.
Definition: freeflow/rans/problem.hh:186
DimVector velocityMinimum(const int elementIdx) const
Definition: freeflow/rans/problem.hh:288
Scalar wallDistance(const int elementIdx) const
Definition: freeflow/rans/problem.hh:267
Scalar storedDensity(const int elementIdx) const
Definition: freeflow/rans/problem.hh:306
Scalar turbulentPrandtlNumber() const
Return the turbulent Prandtl number which is used to convert the eddy viscosity to an eddy thermal c...
Definition: freeflow/rans/problem.hh:218
int wallNormalAxis(const int elementIdx) const
Definition: freeflow/rans/problem.hh:236
unsigned int neighborIndex(const int elementIdx, const int axisIdx, const int sideIdx) const
Definition: freeflow/rans/problem.hh:276
RANSProblemBase(std::shared_ptr< const GridGeometry > gridGeometry, const std::string &paramGroup="")
The constructor.
Definition: freeflow/rans/problem.hh:102
bool isFlatWallBounded() const
Returns whether a given sub control volume face is on a wall.
Definition: freeflow/rans/problem.hh:198
Scalar stressTensorScalarProduct(const int elementIdx) const
Definition: freeflow/rans/problem.hh:297
bool calledUpdateStaticWallProperties
Definition: freeflow/rans/problem.hh:312
bool useWallFunction(const Element &element, const SubControlVolumeFace &scvf, const int &eqIdx) const
Returns whether a wall function should be used at a given face.
Definition: freeflow/rans/problem.hh:165
const Scalar karmanConstant() const
Returns the Karman constant.
Definition: freeflow/rans/problem.hh:207
Scalar storedViscosity(const int elementIdx) const
Definition: freeflow/rans/problem.hh:303
Declares all properties used in Dumux.
Adaption of the fully implicit scheme to the tracer transport model.
The local element solution class for staggered methods.