Line | Branch | Exec | Source |
---|---|---|---|
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-FileCopyrightInfo: Copyright © DuMux Project contributors, see AUTHORS.md in root folder | ||
5 | // SPDX-License-Identifier: GPL-3.0-or-later | ||
6 | // | ||
7 | |||
8 | #ifndef DUMUX_LIDDRIVENCAVITY_EXAMPLE_PROBLEM_HH | ||
9 | #define DUMUX_LIDDRIVENCAVITY_EXAMPLE_PROBLEM_HH | ||
10 | |||
11 | // ## Initial and boundary conditions (`problem.hh`) | ||
12 | // | ||
13 | // This file contains the __problem class__ which defines the initial and boundary | ||
14 | // conditions for the Navier-Stokes single-phase flow simulation. | ||
15 | // | ||
16 | // [[content]] | ||
17 | // | ||
18 | // ### Include files | ||
19 | // | ||
20 | #include <dumux/common/properties.hh> | ||
21 | #include <dumux/common/parameters.hh> | ||
22 | |||
23 | // Include the `NavierStokesBoundaryTypes` class which specifies the boundary types set in this problem. | ||
24 | #include <dumux/freeflow/navierstokes/boundarytypes.hh> | ||
25 | |||
26 | // ### The problem class | ||
27 | // As we are solving a problem related to free flow, we create a new class called `LidDrivenCavityExampleProblem` | ||
28 | // and let it inherit from a base class for the momentum and mass subproblems (selected in `properties.hh`). | ||
29 | // [[codeblock]] | ||
30 | namespace Dumux { | ||
31 | template <class TypeTag, class BaseProblem> | ||
32 | 4 | class LidDrivenCavityExampleProblem : public BaseProblem | |
33 | { | ||
34 | using ParentType = BaseProblem; | ||
35 | |||
36 | using BoundaryTypes = typename ParentType::BoundaryTypes; | ||
37 | using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>; | ||
38 | using FVElementGeometry = typename GridGeometry::LocalView; | ||
39 | using SubControlVolume = typename GridGeometry::SubControlVolume; | ||
40 | using SubControlVolumeFace = typename GridGeometry::SubControlVolumeFace; | ||
41 | using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices; | ||
42 | using InitialValues = typename ParentType::InitialValues; | ||
43 | using Sources = typename ParentType::Sources; | ||
44 | using DirichletValues = typename ParentType::DirichletValues; | ||
45 | using BoundaryFluxes = typename ParentType::BoundaryFluxes; | ||
46 | using Scalar = GetPropType<TypeTag, Properties::Scalar>; | ||
47 | |||
48 | static constexpr auto dimWorld = GridGeometry::GridView::dimensionworld; | ||
49 | using Element = typename FVElementGeometry::Element; | ||
50 | using GlobalPosition = typename Element::Geometry::GlobalCoordinate; | ||
51 | using CouplingManager = GetPropType<TypeTag, Properties::CouplingManager>; | ||
52 | |||
53 | public: | ||
54 | // Within the constructor, we set the lid velocity to a run-time specified value. | ||
55 | 8 | LidDrivenCavityExampleProblem(std::shared_ptr<const GridGeometry> gridGeometry, std::shared_ptr<CouplingManager> couplingManager) | |
56 |
7/20✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 4 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 4 times.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 4 times.
✓ Branch 18 taken 4 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
|
32 | : ParentType(gridGeometry, couplingManager) |
57 | { | ||
58 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
8 | lidVelocity_ = getParam<Scalar>("Problem.LidVelocity"); |
59 | 8 | } | |
60 | // [[/codeblock]] | ||
61 | |||
62 | // #### Boundary conditions | ||
63 | // With the following function we define the __type of boundary conditions__ depending on the location. | ||
64 | // Three types of boundary conditions can be specified: Dirichlet or Neumann boundary conditions. On | ||
65 | // Dirichlet boundaries, the values of the primary variables need to be fixed. On a Neumann boundaries, | ||
66 | // values for derivatives need to be fixed. | ||
67 | // [[codeblock]] | ||
68 | ✗ | BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const | |
69 | { | ||
70 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 125440 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28672 times.
|
154112 | BoundaryTypes values; |
71 | |||
72 | // We set Dirichlet values for the velocity at each boundary. At the same time, | ||
73 | // Neumann (no-flow) conditions hold at the boundaries for the mass model. | ||
74 | if constexpr (ParentType::isMomentumProblem()) | ||
75 | ✗ | values.setAllDirichlet(); | |
76 | else | ||
77 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 125440 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28672 times.
|
154112 | values.setAllNeumann(); |
78 | |||
79 | ✗ | return values; | |
80 | } | ||
81 | // [[/codeblock]] | ||
82 | |||
83 | // The following function specifies the __values on Dirichlet boundaries__. | ||
84 | // We need to define values for the primary variables (velocity). | ||
85 | // [[codeblock]] | ||
86 | ✗ | DirichletValues dirichletAtPos(const GlobalPosition &globalPos) const | |
87 | { | ||
88 | 285616 | DirichletValues values(0.0); | |
89 | |||
90 | if constexpr (ParentType::isMomentumProblem()) | ||
91 | { | ||
92 |
30/80✓ Branch 0 taken 61740 times.
✓ Branch 1 taken 185220 times.
✓ Branch 2 taken 61740 times.
✓ Branch 3 taken 185220 times.
✓ Branch 4 taken 61740 times.
✓ Branch 5 taken 185220 times.
✓ Branch 6 taken 61740 times.
✓ Branch 7 taken 185220 times.
✓ Branch 8 taken 61740 times.
✓ Branch 9 taken 185220 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✗ Branch 26 not taken.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✓ Branch 40 taken 3136 times.
✓ Branch 41 taken 9408 times.
✓ Branch 42 taken 3136 times.
✓ Branch 43 taken 9408 times.
✓ Branch 44 taken 3136 times.
✓ Branch 45 taken 9408 times.
✓ Branch 46 taken 3136 times.
✓ Branch 47 taken 9408 times.
✓ Branch 48 taken 3136 times.
✓ Branch 49 taken 9408 times.
✗ Branch 50 not taken.
✗ Branch 51 not taken.
✗ Branch 52 not taken.
✗ Branch 53 not taken.
✗ Branch 54 not taken.
✗ Branch 55 not taken.
✗ Branch 56 not taken.
✗ Branch 57 not taken.
✗ Branch 58 not taken.
✗ Branch 59 not taken.
✗ Branch 60 not taken.
✗ Branch 61 not taken.
✗ Branch 62 not taken.
✗ Branch 63 not taken.
✗ Branch 64 not taken.
✗ Branch 65 not taken.
✗ Branch 66 not taken.
✗ Branch 67 not taken.
✗ Branch 68 not taken.
✗ Branch 69 not taken.
✓ Branch 70 taken 6630 times.
✓ Branch 71 taken 19482 times.
✓ Branch 72 taken 6630 times.
✓ Branch 73 taken 19482 times.
✓ Branch 74 taken 6630 times.
✓ Branch 75 taken 19482 times.
✓ Branch 76 taken 6630 times.
✓ Branch 77 taken 19482 times.
✓ Branch 78 taken 6630 times.
✓ Branch 79 taken 19482 times.
|
1428080 | if (globalPos[1] > this->gridGeometry().bBoxMax()[1] - eps_) |
93 | 143012 | values[Indices::velocityXIdx] = lidVelocity_; | |
94 | } | ||
95 | |||
96 | 285616 | return values; | |
97 | } | ||
98 | // [[/codeblock]] | ||
99 | |||
100 | // The following function specifies the __values on Neumann boundaries__. | ||
101 | // We define a (zero) mass flux here. | ||
102 | // [[codeblock]] | ||
103 | template<class ElementVolumeVariables, class ElementFluxVariablesCache> | ||
104 | 250880 | BoundaryFluxes neumann(const Element& element, | |
105 | const FVElementGeometry& fvGeometry, | ||
106 | const ElementVolumeVariables& elemVolVars, | ||
107 | const ElementFluxVariablesCache& elemFluxVarsCache, | ||
108 | const SubControlVolumeFace& scvf) const | ||
109 | { | ||
110 | 250880 | BoundaryFluxes values(0.0); | |
111 | |||
112 | if constexpr (!ParentType::isMomentumProblem()) | ||
113 | { | ||
114 | // Density is constant, so inside or outside does not matter. | ||
115 | 501760 | const auto insideDensity = elemVolVars[scvf.insideScvIdx()].density(); | |
116 | |||
117 | // The resulting flux over the boundary is zero anyway (velocity is zero), but this will add some non-zero derivatives to the | ||
118 | // Jacobian and makes the BC more general. | ||
119 | 752640 | values[Indices::conti0EqIdx] = this->faceVelocity(element, fvGeometry, scvf) * insideDensity * scvf.unitOuterNormal(); | |
120 | } | ||
121 | |||
122 | 250880 | return values; | |
123 | } | ||
124 | // [[/codeblock]] | ||
125 | |||
126 | // The problem setup considers closed boundaries everywhere. In order to have a defined pressure level, we impose an __internal Dirichlet | ||
127 | // constraint for pressure__ in a single cell. | ||
128 | // [[codeblock]] | ||
129 | |||
130 | // Use internal Dirichlet constraints for the mass problem. | ||
131 | static constexpr bool enableInternalDirichletConstraints() | ||
132 | { return !ParentType::isMomentumProblem(); } | ||
133 | |||
134 | // Set a fixed pressure a the lower-left cell. | ||
135 | ✗ | std::bitset<DirichletValues::dimension> hasInternalDirichletConstraint(const Element& element, const SubControlVolume& scv) const | |
136 | { | ||
137 | 1793792 | std::bitset<DirichletValues::dimension> values; | |
138 | |||
139 | if constexpr (!ParentType::isMomentumProblem()) | ||
140 | { | ||
141 |
6/10✓ Branch 0 taken 196 times.
✓ Branch 1 taken 802620 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 49 times.
✓ Branch 5 taken 200655 times.
✓ Branch 6 taken 98 times.
✓ Branch 7 taken 790174 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
1793792 | const bool isLowerLeftCell = (scv.dofIndex() == 0); |
142 |
6/10✓ Branch 0 taken 196 times.
✓ Branch 1 taken 802620 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 49 times.
✓ Branch 5 taken 200655 times.
✓ Branch 6 taken 98 times.
✓ Branch 7 taken 790174 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
1793792 | if (isLowerLeftCell) |
143 | 343 | values.set(0); | |
144 | } | ||
145 | |||
146 | ✗ | return values; | |
147 | } | ||
148 | |||
149 | // Specify the pressure value in the internal Dirichlet cell. | ||
150 | ✗ | DirichletValues internalDirichlet(const Element& element, const SubControlVolume& scv) const | |
151 | 200704 | { return DirichletValues(1.1e5); } | |
152 | // [[/codeblock]] | ||
153 | |||
154 | // Setting a __reference pressure__ can help to improve the Newton convergence rate by making the numerical derivatives more exact. | ||
155 | // This is related to floating point arithmetic as pressure values are usually much higher than velocities. | ||
156 | // [[codeblock]] | ||
157 | ✗ | Scalar referencePressure(const Element& element, | |
158 | const FVElementGeometry& fvGeometry, | ||
159 | const SubControlVolumeFace& scvf) const | ||
160 | ✗ | { return 1.0e5; } | |
161 | // [[/codeblock]] | ||
162 | |||
163 | // The following function defines the initial conditions. | ||
164 | // [[codeblock]] | ||
165 | ✗ | InitialValues initialAtPos(const GlobalPosition &globalPos) const | |
166 | { | ||
167 | 24832 | InitialValues values(0.0); | |
168 | |||
169 | if constexpr (!ParentType::isMomentumProblem()) | ||
170 | 8192 | values[Indices::pressureIdx] = 1.0e+5; | |
171 | |||
172 | 16640 | return values; | |
173 | } | ||
174 | // [[/codeblock]] | ||
175 | // Finally, the (private) data members of the problem class. | ||
176 | // [[codeblock]] | ||
177 | private: | ||
178 | static constexpr Scalar eps_ = 1e-6; | ||
179 | Scalar lidVelocity_; | ||
180 | }; | ||
181 | |||
182 | } // end namespace Dumux | ||
183 | // [[/codeblock]] | ||
184 | // [[/content]] | ||
185 | #endif | ||
186 |