diff --git a/dumux/porousmediumflow/compositional/primaryvariableswitch.hh b/dumux/porousmediumflow/compositional/primaryvariableswitch.hh index 49cca272818914e00f886721773ec0ec4f3f9464..d6a02cda41f21fe6bf4d2946c7c3d34c7cb3ea43 100644 --- a/dumux/porousmediumflow/compositional/primaryvariableswitch.hh +++ b/dumux/porousmediumflow/compositional/primaryvariableswitch.hh @@ -203,15 +203,30 @@ public: /*! * \brief Updates the the primary variables state at the boundary. * - * Required when a Dirichlet BC differes from the initial conditon (only for box method). + * Required when a Dirichlet BC differs from the initial condition (only for box method). */ template<class Problem, class GridVariables, class SolutionVector> + [[deprecated("Use updateDirichletConstraints() instead. Will be remove after 3.3")]] void updateBoundary(const Problem& problem, const typename GridVariables::GridGeometry& gridGeometry, GridVariables& gridVariables, SolutionVector& sol) { - if constexpr (GridVariables::GridGeometry::discMethod == DiscretizationMethod::box) + updateDirichletConstraints(problem, gridGeometry, gridVariables, sol); + } + + /*! + * \brief Updates the the primary variables state at the boundary. + * + * Required when a Dirichlet constraint (at a boundary or internal) differs from the initial condition. + */ + template<class Problem, class GridVariables, class SolutionVector> + void updateDirichletConstraints(const Problem& problem, + const typename GridVariables::GridGeometry& gridGeometry, + GridVariables& gridVariables, + SolutionVector& sol) + { + if constexpr (GridVariables::GridGeometry::discMethod == DiscretizationMethod::box || Problem::enableInternalDirichletConstraints()) { std::vector<bool> stateChanged(sol.size(), false); std::size_t countChanged = 0; @@ -221,8 +236,8 @@ public: auto fvGeometry = localView(gridGeometry); fvGeometry.bindElement(element); - // skip if the element is not at a boundary - if (!fvGeometry.hasBoundaryScvf()) + // skip if the element is not at a boundary or if no internal Dirichlet constraints are set + if (!Problem::enableInternalDirichletConstraints() && !fvGeometry.hasBoundaryScvf()) continue; auto elemVolVars = localView(gridVariables.curGridVolVars()); @@ -230,40 +245,32 @@ public: for (const auto& scv : scvs(fvGeometry)) { - // this implies that state is set equal for all scvs associated with the dof const auto dofIdx = scv.dofIndex(); - if (!gridGeometry.dofOnBoundary(dofIdx) || stateChanged[dofIdx]) + + if (stateChanged[dofIdx]) continue; - const auto bcTypes = problem.boundaryTypes(element, scv); - if (bcTypes.hasDirichlet()) + if constexpr (GridVariables::GridGeometry::discMethod == DiscretizationMethod::box) { - const auto dirichletValues = problem.dirichlet(element, scv); - - if (sol[dofIdx].state() != dirichletValues.state()) + if (gridGeometry.dofOnBoundary(dofIdx)) { - if (verbosity() > 1) - std::cout << "Changing primary variable state at boundary (" << sol[dofIdx].state() - << ") to the one given by the Dirichlet condition (" << dirichletValues.state() << ") at dof " << dofIdx - << ", coordinates: " << scv.dofPosition() - << std::endl; - - // make sure the solution vector has the right state (given by the Dirichlet BC) - sol[dofIdx].setState(dirichletValues.state()); - stateChanged[dofIdx] = true; - ++countChanged; - - // overwrite initial with Dirichlet values - for (int eqIdx = 0; eqIdx < SolutionVector::block_type::dimension; ++eqIdx) + if (handleDirichletBoundaryCondition_(problem, element, scv, sol)) { - if (bcTypes.isDirichlet(eqIdx)) - { - const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx); - sol[dofIdx][pvIdx] = dirichletValues[pvIdx]; - } + stateChanged[dofIdx] = true; + ++countChanged; + continue; } } } + + if constexpr (Problem::enableInternalDirichletConstraints()) + { + if (handleInternalDirichletConstraint_(problem, element, scv, sol)) + { + stateChanged[dofIdx] = true; + ++countChanged; + } + } } // update the volVars if caching is enabled @@ -285,7 +292,7 @@ public: } if (verbosity_ > 0 && countChanged > 0) - std::cout << "Changed primary variable states and solution values at boundary to Dirichlet states and values at " << countChanged << " dof locations on processor " + std::cout << "Changed primary variable states and solution values to Dirichlet states and values at " << countChanged << " dof locations on processor " << gridGeometry.gridView().comm().rank() << "." << std::endl; } } @@ -338,10 +345,27 @@ protected: const typename Geometry::SubControlVolume& scv, const Problem& problem) { - if constexpr (Geometry::GridGeometry::discMethod != DiscretizationMethod::box) + // Dofs can be only constrained when using the Box method or when imposing internal Dirichlet constraints + if constexpr (Geometry::GridGeometry::discMethod != DiscretizationMethod::box && !Problem::enableInternalDirichletConstraints()) return false; - else + // check for internally constrained Dofs + const auto isInternallyConstrainedDof = [&]() + { + if constexpr (!Problem::enableInternalDirichletConstraints()) + return false; + else + { + const auto internalDirichletConstraints = problem.hasInternalDirichletConstraint(element, scv); + return internalDirichletConstraints.any(); + } + }; + + if (isInternallyConstrainedDof()) + return true; + + // check for a Dirichlet BC when using the Box method + if constexpr (Geometry::GridGeometry::discMethod == DiscretizationMethod::box) { if (!fvGeometry.hasBoundaryScvf()) return false; @@ -353,9 +377,87 @@ protected: const auto bcTypes = problem.boundaryTypes(element, scv); if (bcTypes.hasDirichlet()) return true; + } - return false; + return false; + } + + template<class Problem, class Element, class SubControlVolume, class SolutionVector> + bool handleDirichletBoundaryCondition_(const Problem& problem, + const Element& element, + const SubControlVolume& scv, + SolutionVector& sol) + { + bool changed = false; + const auto bcTypes = problem.boundaryTypes(element, scv); + if (bcTypes.hasDirichlet()) + { + const auto dirichletValues = problem.dirichlet(element, scv); + const auto dofIdx = scv.dofIndex(); + + if (sol[dofIdx].state() != dirichletValues.state()) + { + if (verbosity() > 1) + std::cout << "Changing primary variable state at boundary (" << sol[dofIdx].state() + << ") to the one given by the Dirichlet condition (" << dirichletValues.state() << ") at dof " << dofIdx + << ", coordinates: " << scv.dofPosition() + << std::endl; + + // make sure the solution vector has the right state (given by the Dirichlet BC) + sol[dofIdx].setState(dirichletValues.state()); + changed = true; + + // overwrite initial with Dirichlet values + for (int eqIdx = 0; eqIdx < SolutionVector::block_type::dimension; ++eqIdx) + { + if (bcTypes.isDirichlet(eqIdx)) + { + const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx); + sol[dofIdx][pvIdx] = dirichletValues[pvIdx]; + } + } + } } + + return changed; + } + + template<class Problem, class Element, class SubControlVolume, class SolutionVector> + bool handleInternalDirichletConstraint_(const Problem& problem, + const Element& element, + const SubControlVolume& scv, + SolutionVector& sol) + { + bool changed = false; + + const auto internalDirichletConstraints = problem.hasInternalDirichletConstraint(element, scv); + if (internalDirichletConstraints.none()) + return changed; + + const auto dirichletValues = problem.internalDirichlet(element, scv); + const auto dofIdx = scv.dofIndex(); + + if (sol[dofIdx].state() != dirichletValues.state()) + { + if (verbosity() > 1) + std::cout << "Changing primary variable state at internal DOF (" << sol[dofIdx].state() + << ") to the one given by the internal Dirichlet constraint (" << dirichletValues.state() << ") at dof " << dofIdx + << ", coordinates: " << scv.dofPosition() + << std::endl; + + // make sure the solution vector has the right state (given by the Dirichlet constraint) + sol[dofIdx].setState(dirichletValues.state()); + changed = true; + + // overwrite initial with Dirichlet values + for (int pvIdx = 0; pvIdx < SolutionVector::block_type::dimension; ++pvIdx) + { + if (internalDirichletConstraints[pvIdx]) + sol[dofIdx][pvIdx] = dirichletValues[pvIdx]; + } + } + + return changed; } std::vector<bool> wasSwitched_;