3.5-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
compositional/primaryvariableswitch.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_PRIMARY_VARIABLE_SWITCH_HH
26#define DUMUX_PRIMARY_VARIABLE_SWITCH_HH
27
28#include <iostream>
29
30#include <dune/common/exceptions.hh>
31#include <dune/common/fvector.hh>
34
35namespace Dumux {
36
42{
43public:
44 template<typename... Args>
46
47 template<typename... Args> void reset(Args&&...) {}
48 template<typename... Args> bool wasSwitched(Args&&...) const { return false; }
49 template<typename... Args> bool update(Args&&...) { return false; }
50 template<typename... Args> void updateSwitchedVolVars(Args&&...) {}
51 template<typename... Args> void updateSwitchedFluxVarsCache(Args&&...) {}
52 template<typename... Args> void updateDirichletConstraints(Args&&...) {}
53};
54
59template<class Implementation>
61{
62public:
64 : verbosity_(verbosity)
65 {}
66
68 bool wasSwitched(std::size_t dofIdxGlobal) const
69 {
70 return wasSwitched_[dofIdxGlobal];
71 }
72
74 void reset(const std::size_t numDofs)
75 {
76 wasSwitched_.assign(numDofs, false);
77 }
78
87 template<class SolutionVector, class GridVariables, class Problem>
88 bool update(SolutionVector& curSol,
89 GridVariables& gridVariables,
90 const Problem& problem,
91 const typename GridVariables::GridGeometry& gridGeometry)
92 {
93 bool switched = false;
94 visited_.assign(wasSwitched_.size(), false);
95 std::size_t countSwitched = 0;
96
97 auto fvGeometry = localView(gridGeometry);
98 auto elemVolVars = localView(gridVariables.curGridVolVars());
99
100 for (const auto& element : elements(gridGeometry.gridView()))
101 {
102 // make sure FVElementGeometry is bound to the element
103 fvGeometry.bindElement(element);
104 elemVolVars.bindElement(element, fvGeometry, curSol);
105
106 const auto curElemSol = elementSolution(element, curSol, gridGeometry);
107 for (auto&& scv : scvs(fvGeometry))
108 {
109 if (!asImp_().skipDof_(element, fvGeometry, scv, problem))
110 {
111 const auto dofIdxGlobal = scv.dofIndex();
112 // Note this implies that volume variables don't differ
113 // in any sub control volume associated with the dof!
114 visited_[dofIdxGlobal] = true;
115 // Compute volVars on which grounds we decide
116 // if we need to switch the primary variables
117 auto& volVars = getVolVarAccess_(gridVariables.curGridVolVars(), elemVolVars, scv);
118 volVars.update(curElemSol, problem, element, scv);
119
120 if (asImp_().update_(curSol[dofIdxGlobal], volVars, dofIdxGlobal, scv.dofPosition()))
121 {
122 switched = true;
123 ++countSwitched;
124 }
125 }
126 }
127 }
128
129 if (verbosity_ > 0 && countSwitched > 0)
130 std::cout << "Switched primary variables at " << countSwitched << " dof locations on processor "
131 << gridGeometry.gridView().comm().rank() << "." << std::endl;
132
133 // make sure that if there was a variable switch in an
134 // other partition we will also set the switch flag for our partition.
135 if (gridGeometry.gridView().comm().size() > 1)
136 switched = gridGeometry.gridView().comm().max(switched);
137
138 return switched;
139 }
140
147 template<class Problem, class GridVariables, class SolutionVector>
148 void updateSwitchedVolVars(const Problem& problem,
149 const typename GridVariables::GridGeometry::GridView::template Codim<0>::Entity& element,
150 const typename GridVariables::GridGeometry& gridGeometry,
151 GridVariables& gridVariables,
152 const SolutionVector& sol)
153 {
154 if constexpr (GridVariables::GridVolumeVariables::cachingEnabled)
155 {
156 // make sure FVElementGeometry is bound to the element
157 const auto fvGeometry = localView(gridGeometry).bindElement(element);
158
159 // update the secondary variables if global caching is enabled
160 for (auto&& scv : scvs(fvGeometry))
161 {
162 const auto dofIdxGlobal = scv.dofIndex();
163 if (asImp_().wasSwitched(dofIdxGlobal))
164 {
165 const auto elemSol = elementSolution(element, sol, gridGeometry);
166 auto& volVars = gridVariables.curGridVolVars().volVars(scv);
167 volVars.update(elemSol, problem, element, scv);
168 }
169 }
170 }
171 }
172
179 template<class Problem, class GridVariables, class SolutionVector>
180 void updateSwitchedFluxVarsCache(const Problem& problem,
181 const typename GridVariables::GridGeometry::GridView::template Codim<0>::Entity& element,
182 const typename GridVariables::GridGeometry& gridGeometry,
183 GridVariables& gridVariables,
184 const SolutionVector& sol)
185 {
186 if constexpr (GridVariables::GridFluxVariablesCache::cachingEnabled
187 && GridVariables::GridGeometry::discMethod != DiscretizationMethods::box)
188 {
189 // update the flux variables if global caching is enabled
190 const auto dofIdxGlobal = gridGeometry.dofMapper().index(element);
191
192 if (asImp_().wasSwitched(dofIdxGlobal))
193 {
194 // make sure FVElementGeometry and the volume variables are bound
195 const auto fvGeometry = localView(gridGeometry).bind(element);
196 const auto curElemVolVars = localView(gridVariables.curGridVolVars()).bind(element, fvGeometry, sol);
197 gridVariables.gridFluxVarsCache().updateElement(element, fvGeometry, curElemVolVars);
198 }
199 }
200 }
201
207 template<class Problem, class GridVariables, class SolutionVector>
208 void updateDirichletConstraints(const Problem& problem,
209 const typename GridVariables::GridGeometry& gridGeometry,
210 GridVariables& gridVariables,
211 SolutionVector& sol)
212 {
213 if constexpr (GridVariables::GridGeometry::discMethod == DiscretizationMethods::box || Problem::enableInternalDirichletConstraints())
214 {
215 std::vector<bool> stateChanged(sol.size(), false);
216 std::size_t countChanged = 0;
217
218 for (const auto& element : elements(gridGeometry.gridView()))
219 {
220 const auto fvGeometry = localView(gridGeometry).bindElement(element);
221
222 // skip if the element is not at a boundary or if no internal Dirichlet constraints are set
223 if (!Problem::enableInternalDirichletConstraints() && !fvGeometry.hasBoundaryScvf())
224 continue;
225
226 const auto elemVolVars = localView(gridVariables.curGridVolVars()).bindElement(element, fvGeometry, sol);
227
228 for (const auto& scv : scvs(fvGeometry))
229 {
230 const auto dofIdx = scv.dofIndex();
231
232 if (stateChanged[dofIdx])
233 continue;
234
235 if constexpr (GridVariables::GridGeometry::discMethod == DiscretizationMethods::box)
236 {
237 if (gridGeometry.dofOnBoundary(dofIdx))
238 {
239 if (handleDirichletBoundaryCondition_(problem, element, scv, sol))
240 {
241 stateChanged[dofIdx] = true;
242 ++countChanged;
243 continue;
244 }
245 }
246 }
247
248 if constexpr (Problem::enableInternalDirichletConstraints())
249 {
250 if (handleInternalDirichletConstraint_(problem, element, scv, sol))
251 {
252 stateChanged[dofIdx] = true;
253 ++countChanged;
254 }
255 }
256 }
257
258 // update the volVars if caching is enabled
259 if constexpr (GridVariables::GridVolumeVariables::cachingEnabled)
260 {
261 if (countChanged > 0)
262 {
263 const auto curElemSol = elementSolution(element, sol, gridGeometry);
264 for (const auto& scv : scvs(fvGeometry))
265 {
266 if (stateChanged[scv.dofIndex()])
267 {
268 auto& volVars = getVolVarAccess_(gridVariables.curGridVolVars(), elemVolVars, scv);
269 volVars.update(curElemSol, problem, element, scv);
270 }
271 }
272 }
273 }
274 }
275
276 if (verbosity_ > 0 && countChanged > 0)
277 std::cout << "Changed primary variable states and solution values to Dirichlet states and values at " << countChanged << " dof locations on processor "
278 << gridGeometry.gridView().comm().rank() << "." << std::endl;
279 }
280 }
281
283 int verbosity() const
284 { return verbosity_; }
285
286protected:
287
289 Implementation &asImp_()
290 { return *static_cast<Implementation*>(this); }
291
293 const Implementation &asImp_() const
294 { return *static_cast<const Implementation*>(this); }
295
296 // Perform variable switch at a degree of freedom location
297 template<class VolumeVariables, class GlobalPosition>
298 bool update_(typename VolumeVariables::PrimaryVariables& priVars,
299 const VolumeVariables& volVars,
300 std::size_t dofIdxGlobal,
301 const GlobalPosition& globalPos)
302 {
303 // evaluate if the primary variable switch would switch
304 // to be implemented by the deriving class
305 DUNE_THROW(Dune::NotImplemented, "This model seems to use a primary variable switch but none is implemented!");
306 }
307
308 // Maybe skip the degree of freedom (do not switch variables at this dof)
309 template<class Geometry, class Problem>
310 bool skipDof_(const typename Geometry::GridGeometry::GridView::template Codim<0>::Entity& element,
311 const Geometry& fvGeometry,
312 const typename Geometry::SubControlVolume& scv,
313 const Problem& problem)
314 {
315 if (visited_[scv.dofIndex()])
316 return true;
317
318 if (isConstrainedDof_(element, fvGeometry, scv, problem))
319 return true;
320
321 return false;
322 }
323
324 template<class Geometry, class Problem>
325 bool isConstrainedDof_(const typename Geometry::GridGeometry::GridView::template Codim<0>::Entity& element,
326 const Geometry& fvGeometry,
327 const typename Geometry::SubControlVolume& scv,
328 const Problem& problem)
329 {
330 // Dofs can be only constrained when using the Box method or when imposing internal Dirichlet constraints
331 if constexpr (Geometry::GridGeometry::discMethod != DiscretizationMethods::box && !Problem::enableInternalDirichletConstraints())
332 return false;
333
334 // check for internally constrained Dofs
335 const auto isInternallyConstrainedDof = [&]()
336 {
337 if constexpr (!Problem::enableInternalDirichletConstraints())
338 return false;
339 else
340 {
341 const auto internalDirichletConstraints = problem.hasInternalDirichletConstraint(element, scv);
342 return internalDirichletConstraints.any();
343 }
344 };
345
346 if (isInternallyConstrainedDof())
347 return true;
348
349 // check for a Dirichlet BC when using the Box method
350 if constexpr (Geometry::GridGeometry::discMethod == DiscretizationMethods::box)
351 {
352 if (!fvGeometry.hasBoundaryScvf())
353 return false;
354
355 const auto dofIdx = scv.dofIndex();
356 if (!fvGeometry.gridGeometry().dofOnBoundary(dofIdx))
357 return false;
358
359 const auto bcTypes = problem.boundaryTypes(element, scv);
360 if (bcTypes.hasDirichlet())
361 return true;
362 }
363
364 return false;
365 }
366
367 template<class Problem, class Element, class SubControlVolume, class SolutionVector>
368 bool handleDirichletBoundaryCondition_(const Problem& problem,
369 const Element& element,
370 const SubControlVolume& scv,
371 SolutionVector& sol)
372 {
373 bool changed = false;
374 const auto bcTypes = problem.boundaryTypes(element, scv);
375 if (bcTypes.hasDirichlet())
376 {
377 const auto dirichletValues = problem.dirichlet(element, scv);
378 const auto dofIdx = scv.dofIndex();
379
380 if (sol[dofIdx].state() != dirichletValues.state())
381 {
382 if (verbosity() > 1)
383 std::cout << "Changing primary variable state at boundary (" << sol[dofIdx].state()
384 << ") to the one given by the Dirichlet condition (" << dirichletValues.state() << ") at dof " << dofIdx
385 << ", coordinates: " << scv.dofPosition()
386 << std::endl;
387
388 // make sure the solution vector has the right state (given by the Dirichlet BC)
389 sol[dofIdx].setState(dirichletValues.state());
390 changed = true;
391
392 // overwrite initial with Dirichlet values
393 for (int eqIdx = 0; eqIdx < SolutionVector::block_type::dimension; ++eqIdx)
394 {
395 if (bcTypes.isDirichlet(eqIdx))
396 {
397 const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
398 sol[dofIdx][pvIdx] = dirichletValues[pvIdx];
399 }
400 }
401 }
402 }
403
404 return changed;
405 }
406
407 template<class Problem, class Element, class SubControlVolume, class SolutionVector>
408 bool handleInternalDirichletConstraint_(const Problem& problem,
409 const Element& element,
410 const SubControlVolume& scv,
411 SolutionVector& sol)
412 {
413 bool changed = false;
414
415 const auto internalDirichletConstraints = problem.hasInternalDirichletConstraint(element, scv);
416 if (internalDirichletConstraints.none())
417 return changed;
418
419 const auto dirichletValues = problem.internalDirichlet(element, scv);
420 const auto dofIdx = scv.dofIndex();
421
422 if (sol[dofIdx].state() != dirichletValues.state())
423 {
424 if (verbosity() > 1)
425 std::cout << "Changing primary variable state at internal DOF (" << sol[dofIdx].state()
426 << ") to the one given by the internal Dirichlet constraint (" << dirichletValues.state() << ") at dof " << dofIdx
427 << ", coordinates: " << scv.dofPosition()
428 << std::endl;
429
430 // make sure the solution vector has the right state (given by the Dirichlet constraint)
431 sol[dofIdx].setState(dirichletValues.state());
432 changed = true;
433
434 // overwrite initial with Dirichlet values
435 for (int pvIdx = 0; pvIdx < SolutionVector::block_type::dimension; ++pvIdx)
436 {
437 if (internalDirichletConstraints[pvIdx])
438 sol[dofIdx][pvIdx] = dirichletValues[pvIdx];
439 }
440 }
441
442 return changed;
443 }
444
445 std::vector<bool> wasSwitched_;
446 std::vector<bool> visited_;
447
448private:
449 template<class GridVolumeVariables, class ElementVolumeVariables, class SubControlVolume>
450 typename GridVolumeVariables::VolumeVariables&
451 getVolVarAccess_(GridVolumeVariables& gridVolVars, ElementVolumeVariables& elemVolVars, const SubControlVolume& scv) const
452 {
453 if constexpr (GridVolumeVariables::cachingEnabled)
454 return gridVolVars.volVars(scv);
455 else
456 return elemVolVars[scv];
457 }
458
459 int verbosity_;
460};
461
462} // end namespace dumux
463
464#endif
Element solution classes and factory functions.
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
auto elementSolution(const Element &element, const SolutionVector &sol, const GridGeometry &gg) -> std::enable_if_t< GridGeometry::discMethod==DiscretizationMethods::box, BoxElementSolution< typename GridGeometry::LocalView, std::decay_t< decltype(std::declval< SolutionVector >()[0])> > >
Make an element solution for box schemes.
Definition: box/elementsolution.hh:118
Definition: adapt.hh:29
constexpr Box box
Definition: method.hh:139
Empty class for models without pri var switch.
Definition: compositional/primaryvariableswitch.hh:42
void reset(Args &&...)
Definition: compositional/primaryvariableswitch.hh:47
void updateSwitchedVolVars(Args &&...)
Definition: compositional/primaryvariableswitch.hh:50
NoPrimaryVariableSwitch(Args &&...)
Definition: compositional/primaryvariableswitch.hh:45
bool wasSwitched(Args &&...) const
Definition: compositional/primaryvariableswitch.hh:48
bool update(Args &&...)
Definition: compositional/primaryvariableswitch.hh:49
void updateDirichletConstraints(Args &&...)
Definition: compositional/primaryvariableswitch.hh:52
void updateSwitchedFluxVarsCache(Args &&...)
Definition: compositional/primaryvariableswitch.hh:51
The primary variable switch controlling the phase presence state variable.
Definition: compositional/primaryvariableswitch.hh:61
bool wasSwitched(std::size_t dofIdxGlobal) const
If the primary variables were recently switched.
Definition: compositional/primaryvariableswitch.hh:68
std::vector< bool > wasSwitched_
Definition: compositional/primaryvariableswitch.hh:445
void updateSwitchedVolVars(const Problem &problem, const typename GridVariables::GridGeometry::GridView::template Codim< 0 >::Entity &element, const typename GridVariables::GridGeometry &gridGeometry, GridVariables &gridVariables, const SolutionVector &sol)
Updates the volume variables whose primary variables were switched.
Definition: compositional/primaryvariableswitch.hh:148
bool isConstrainedDof_(const typename Geometry::GridGeometry::GridView::template Codim< 0 >::Entity &element, const Geometry &fvGeometry, const typename Geometry::SubControlVolume &scv, const Problem &problem)
Definition: compositional/primaryvariableswitch.hh:325
bool handleDirichletBoundaryCondition_(const Problem &problem, const Element &element, const SubControlVolume &scv, SolutionVector &sol)
Definition: compositional/primaryvariableswitch.hh:368
PrimaryVariableSwitch(int verbosity=1)
Definition: compositional/primaryvariableswitch.hh:63
bool handleInternalDirichletConstraint_(const Problem &problem, const Element &element, const SubControlVolume &scv, SolutionVector &sol)
Definition: compositional/primaryvariableswitch.hh:408
Implementation & asImp_()
Return actual implementation (static polymorphism)
Definition: compositional/primaryvariableswitch.hh:289
void updateDirichletConstraints(const Problem &problem, const typename GridVariables::GridGeometry &gridGeometry, GridVariables &gridVariables, SolutionVector &sol)
Updates the the primary variables state at the boundary.
Definition: compositional/primaryvariableswitch.hh:208
bool skipDof_(const typename Geometry::GridGeometry::GridView::template Codim< 0 >::Entity &element, const Geometry &fvGeometry, const typename Geometry::SubControlVolume &scv, const Problem &problem)
Definition: compositional/primaryvariableswitch.hh:310
const Implementation & asImp_() const
Return actual implementation (static polymorphism)
Definition: compositional/primaryvariableswitch.hh:293
bool update(SolutionVector &curSol, GridVariables &gridVariables, const Problem &problem, const typename GridVariables::GridGeometry &gridGeometry)
Updates the variable switch / phase presence.
Definition: compositional/primaryvariableswitch.hh:88
int verbosity() const
The verbosity level.
Definition: compositional/primaryvariableswitch.hh:283
void reset(const std::size_t numDofs)
Reset all flags.
Definition: compositional/primaryvariableswitch.hh:74
bool update_(typename VolumeVariables::PrimaryVariables &priVars, const VolumeVariables &volVars, std::size_t dofIdxGlobal, const GlobalPosition &globalPos)
Definition: compositional/primaryvariableswitch.hh:298
std::vector< bool > visited_
Definition: compositional/primaryvariableswitch.hh:446
void updateSwitchedFluxVarsCache(const Problem &problem, const typename GridVariables::GridGeometry::GridView::template Codim< 0 >::Entity &element, const typename GridVariables::GridGeometry &gridGeometry, GridVariables &gridVariables, const SolutionVector &sol)
Updates the fluxVars cache for dof whose primary variables were switched.
Definition: compositional/primaryvariableswitch.hh:180