13#ifndef DUMUX_PRIMARY_VARIABLE_SWITCH_HH
14#define DUMUX_PRIMARY_VARIABLE_SWITCH_HH
18#include <dune/common/exceptions.hh>
19#include <dune/common/fvector.hh>
32 template<
typename... Args>
35 template<
typename... Args>
void reset(Args&&...) {}
36 template<
typename... Args>
bool wasSwitched(Args&&...)
const {
return false; }
37 template<
typename... Args>
bool update(Args&&...) {
return false; }
47template<
class Implementation>
62 void reset(
const std::size_t numDofs)
75 template<
class SolutionVector,
class Gr
idVariables,
class Problem>
77 GridVariables& gridVariables,
78 const Problem& problem,
79 const typename GridVariables::GridGeometry& gridGeometry)
81 bool switched =
false;
82 bool successfulUpdate =
false;
83 const auto& comm = gridGeometry.gridView().comm();
87 std::size_t countSwitched = 0;
89 auto fvGeometry =
localView(gridGeometry);
90 auto elemVolVars =
localView(gridVariables.curGridVolVars());
92 for (
const auto& element : elements(gridGeometry.gridView()))
95 fvGeometry.bindElement(element);
96 elemVolVars.bindElement(element, fvGeometry, curSol);
99 for (
auto&& scv :
scvs(fvGeometry))
103 const auto dofIdxGlobal = scv.dofIndex();
109 auto& volVars = getVolVarAccess_(gridVariables.curGridVolVars(), elemVolVars, scv);
110 volVars.update(curElemSol, problem, element, scv);
112 if (
asImp_().
update_(curSol[dofIdxGlobal], volVars, dofIdxGlobal, scv.dofPosition()))
121 if (verbosity_ > 0 && countSwitched > 0)
122 std::cout <<
"Switched primary variables at " << countSwitched <<
" dof locations on processor "
123 << comm.rank() <<
"." << std::endl;
125 successfulUpdate =
true;
130 std::cout <<
"Primary variable switch caught: \"" << e.what() <<
"\"\n";
132 successfulUpdate =
false;
136 int successfulUpdateRemote =
static_cast<int>(successfulUpdate);
138 successfulUpdateRemote = comm.min(
static_cast<int>(successfulUpdate));
140 if (!successfulUpdate)
141 DUNE_THROW(
NumericalProblem,
"Primary variable switch caught exception on process " << comm.rank());
143 else if (!successfulUpdateRemote)
144 DUNE_THROW(
NumericalProblem,
"Primary variable switch caught exception on a remote process");
149 switched = comm.max(switched);
160 template<
class Problem,
class Gr
idVariables,
class SolutionVector>
162 const typename GridVariables::GridGeometry::GridView::template Codim<0>::Entity& element,
163 const typename GridVariables::GridGeometry& gridGeometry,
164 GridVariables& gridVariables,
165 const SolutionVector& sol)
167 if constexpr (GridVariables::GridVolumeVariables::cachingEnabled)
170 const auto fvGeometry =
localView(gridGeometry).bindElement(element);
173 for (
auto&& scv :
scvs(fvGeometry))
175 const auto dofIdxGlobal = scv.dofIndex();
179 auto& volVars = gridVariables.curGridVolVars().volVars(scv);
180 volVars.update(elemSol, problem, element, scv);
192 template<
class Problem,
class Gr
idVariables,
class SolutionVector>
194 const typename GridVariables::GridGeometry::GridView::template Codim<0>::Entity& element,
195 const typename GridVariables::GridGeometry& gridGeometry,
196 GridVariables& gridVariables,
197 const SolutionVector& sol)
199 if constexpr (GridVariables::GridFluxVariablesCache::cachingEnabled
203 const auto dofIdxGlobal = gridGeometry.dofMapper().index(element);
205 if (
asImp_().wasSwitched(dofIdxGlobal))
208 const auto fvGeometry =
localView(gridGeometry).bind(element);
209 const auto curElemVolVars =
localView(gridVariables.curGridVolVars()).bind(element, fvGeometry, sol);
210 gridVariables.gridFluxVarsCache().updateElement(element, fvGeometry, curElemVolVars);
220 template<
class Problem,
class Gr
idVariables,
class SolutionVector>
222 const typename GridVariables::GridGeometry& gridGeometry,
223 GridVariables& gridVariables,
226 if constexpr (GridVariables::GridGeometry::discMethod ==
DiscretizationMethods::box || Problem::enableInternalDirichletConstraints())
228 std::vector<bool> stateChanged(sol.size(),
false);
229 std::size_t countChanged = 0;
231 for (
const auto& element : elements(gridGeometry.gridView()))
233 const auto fvGeometry =
localView(gridGeometry).bindElement(element);
236 if (!Problem::enableInternalDirichletConstraints() && !fvGeometry.hasBoundaryScvf())
239 const auto elemVolVars =
localView(gridVariables.curGridVolVars()).bindElement(element, fvGeometry, sol);
241 for (
const auto& scv :
scvs(fvGeometry))
243 const auto dofIdx = scv.dofIndex();
245 if (stateChanged[dofIdx])
250 if (gridGeometry.dofOnBoundary(dofIdx))
254 stateChanged[dofIdx] =
true;
261 if constexpr (Problem::enableInternalDirichletConstraints())
265 stateChanged[dofIdx] =
true;
272 if constexpr (GridVariables::GridVolumeVariables::cachingEnabled)
274 if (countChanged > 0)
277 for (
const auto& scv :
scvs(fvGeometry))
279 if (stateChanged[scv.dofIndex()])
281 auto& volVars = getVolVarAccess_(gridVariables.curGridVolVars(), elemVolVars, scv);
282 volVars.update(curElemSol, problem, element, scv);
289 if (verbosity_ > 0 && countChanged > 0)
290 std::cout <<
"Changed primary variable states and solution values to Dirichlet states and values at " << countChanged <<
" dof locations on processor "
291 << gridGeometry.gridView().comm().rank() <<
"." << std::endl;
297 {
return verbosity_; }
303 {
return *
static_cast<Implementation*
>(
this); }
307 {
return *
static_cast<const Implementation*
>(
this); }
310 template<
class VolumeVariables,
class GlobalPosition>
311 bool update_(
typename VolumeVariables::PrimaryVariables& priVars,
312 const VolumeVariables& volVars,
313 std::size_t dofIdxGlobal,
314 const GlobalPosition& globalPos)
318 DUNE_THROW(Dune::NotImplemented,
"This model seems to use a primary variable switch but none is implemented!");
322 template<
class Geometry,
class Problem>
323 bool skipDof_(
const typename Geometry::GridGeometry::GridView::template Codim<0>::Entity& element,
324 const Geometry& fvGeometry,
325 const typename Geometry::SubControlVolume& scv,
326 const Problem& problem)
337 template<
class Geometry,
class Problem>
338 bool isConstrainedDof_(
const typename Geometry::GridGeometry::GridView::template Codim<0>::Entity& element,
339 const Geometry& fvGeometry,
340 const typename Geometry::SubControlVolume& scv,
341 const Problem& problem)
344 if constexpr (Geometry::GridGeometry::discMethod !=
DiscretizationMethods::box && !Problem::enableInternalDirichletConstraints())
348 const auto isInternallyConstrainedDof = [&]()
350 if constexpr (!Problem::enableInternalDirichletConstraints())
354 const auto internalDirichletConstraints = problem.hasInternalDirichletConstraint(element, scv);
355 return internalDirichletConstraints.any();
359 if (isInternallyConstrainedDof())
365 if (!fvGeometry.hasBoundaryScvf())
368 const auto dofIdx = scv.dofIndex();
369 if (!fvGeometry.gridGeometry().dofOnBoundary(dofIdx))
372 const auto bcTypes = problem.boundaryTypes(element, scv);
373 if (bcTypes.hasDirichlet())
380 template<
class Problem,
class Element,
class SubControlVolume,
class SolutionVector>
382 const Element& element,
383 const SubControlVolume& scv,
386 bool changed =
false;
387 const auto bcTypes = problem.boundaryTypes(element, scv);
388 if (bcTypes.hasDirichlet())
390 const auto dirichletValues = problem.dirichlet(element, scv);
391 const auto dofIdx = scv.dofIndex();
393 if (sol[dofIdx].state() != dirichletValues.state())
396 std::cout <<
"Changing primary variable state at boundary (" << sol[dofIdx].state()
397 <<
") to the one given by the Dirichlet condition (" << dirichletValues.state() <<
") at dof " << dofIdx
398 <<
", coordinates: " << scv.dofPosition()
402 sol[dofIdx].setState(dirichletValues.state());
406 for (
int eqIdx = 0; eqIdx < SolutionVector::block_type::dimension; ++eqIdx)
408 if (bcTypes.isDirichlet(eqIdx))
410 const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
411 sol[dofIdx][pvIdx] = dirichletValues[pvIdx];
420 template<
class Problem,
class Element,
class SubControlVolume,
class SolutionVector>
422 const Element& element,
423 const SubControlVolume& scv,
426 bool changed =
false;
428 const auto internalDirichletConstraints = problem.hasInternalDirichletConstraint(element, scv);
429 if (internalDirichletConstraints.none())
432 const auto dirichletValues = problem.internalDirichlet(element, scv);
433 const auto dofIdx = scv.dofIndex();
435 if (sol[dofIdx].state() != dirichletValues.state())
438 std::cout <<
"Changing primary variable state at internal DOF (" << sol[dofIdx].state()
439 <<
") to the one given by the internal Dirichlet constraint (" << dirichletValues.state() <<
") at dof " << dofIdx
440 <<
", coordinates: " << scv.dofPosition()
444 sol[dofIdx].setState(dirichletValues.state());
448 for (
int pvIdx = 0; pvIdx < SolutionVector::block_type::dimension; ++pvIdx)
450 if (internalDirichletConstraints[pvIdx])
451 sol[dofIdx][pvIdx] = dirichletValues[pvIdx];
462 template<
class Gr
idVolumeVariables,
class ElementVolumeVariables,
class SubControlVolume>
463 typename GridVolumeVariables::VolumeVariables&
464 getVolVarAccess_(GridVolumeVariables& gridVolVars, ElementVolumeVariables& elemVolVars,
const SubControlVolume& scv)
const
466 if constexpr (GridVolumeVariables::cachingEnabled)
467 return gridVolVars.volVars(scv);
469 return elemVolVars[scv];
Empty class for models without pri var switch.
Definition: compositional/primaryvariableswitch.hh:30
void reset(Args &&...)
Definition: compositional/primaryvariableswitch.hh:35
void updateSwitchedVolVars(Args &&...)
Definition: compositional/primaryvariableswitch.hh:38
NoPrimaryVariableSwitch(Args &&...)
Definition: compositional/primaryvariableswitch.hh:33
bool wasSwitched(Args &&...) const
Definition: compositional/primaryvariableswitch.hh:36
bool update(Args &&...)
Definition: compositional/primaryvariableswitch.hh:37
void updateDirichletConstraints(Args &&...)
Definition: compositional/primaryvariableswitch.hh:40
void updateSwitchedFluxVarsCache(Args &&...)
Definition: compositional/primaryvariableswitch.hh:39
Exception thrown if a fixable numerical problem occurs.
Definition: exceptions.hh:27
The primary variable switch controlling the phase presence state variable.
Definition: compositional/primaryvariableswitch.hh:49
bool wasSwitched(std::size_t dofIdxGlobal) const
If the primary variables were recently switched.
Definition: compositional/primaryvariableswitch.hh:56
std::vector< bool > wasSwitched_
Definition: compositional/primaryvariableswitch.hh:458
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:161
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:338
bool handleDirichletBoundaryCondition_(const Problem &problem, const Element &element, const SubControlVolume &scv, SolutionVector &sol)
Definition: compositional/primaryvariableswitch.hh:381
PrimaryVariableSwitch(int verbosity=1)
Definition: compositional/primaryvariableswitch.hh:51
bool handleInternalDirichletConstraint_(const Problem &problem, const Element &element, const SubControlVolume &scv, SolutionVector &sol)
Definition: compositional/primaryvariableswitch.hh:421
Implementation & asImp_()
Return actual implementation (static polymorphism)
Definition: compositional/primaryvariableswitch.hh:302
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:221
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:323
const Implementation & asImp_() const
Return actual implementation (static polymorphism)
Definition: compositional/primaryvariableswitch.hh:306
bool update(SolutionVector &curSol, GridVariables &gridVariables, const Problem &problem, const typename GridVariables::GridGeometry &gridGeometry)
Updates the variable switch / phase presence.
Definition: compositional/primaryvariableswitch.hh:76
int verbosity() const
The verbosity level.
Definition: compositional/primaryvariableswitch.hh:296
void reset(const std::size_t numDofs)
Reset all flags.
Definition: compositional/primaryvariableswitch.hh:62
bool update_(typename VolumeVariables::PrimaryVariables &priVars, const VolumeVariables &volVars, std::size_t dofIdxGlobal, const GlobalPosition &globalPos)
Definition: compositional/primaryvariableswitch.hh:311
std::vector< bool > visited_
Definition: compositional/primaryvariableswitch.hh:459
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:193
Element solution classes and factory functions.
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition: localview.hh:26
auto elementSolution(const Element &element, const SolutionVector &sol, const GridGeometry &gg) -> std::enable_if_t< GridGeometry::discMethod==DiscretizationMethods::cctpfa||GridGeometry::discMethod==DiscretizationMethods::ccmpfa, CCElementSolution< typename GridGeometry::LocalView, std::decay_t< decltype(std::declval< SolutionVector >()[0])> > >
Make an element solution for cell-centered schemes.
Definition: cellcentered/elementsolution.hh:101
The available discretization methods in Dumux.
constexpr Box box
Definition: method.hh:147
std::ranges::range auto scvs(const FVElementGeometry &fvGeometry, const LocalDof &localDof)
Definition: localdof.hh:79