13#ifndef DUMUX_MULTIDOMAIN_MULTIBINARY_COUPLINGMANAGER_HH 
   14#define DUMUX_MULTIDOMAIN_MULTIBINARY_COUPLINGMANAGER_HH 
   18#include <dune/common/hybridutilities.hh> 
   26template <std::
size_t, 
typename Tuple>
 
   29template <std::size_t i, 
typename... Indices>
 
   31: std::disjunction<std::is_same<Dune::index_constant<i>, Indices>...>
 
 
   48template<
class MDTraits, 
class CouplingMap, 
class ...CouplingMgrs>
 
   52    template<std::
size_t id>
 
   53    using SubDomainTypeTag = 
typename MDTraits::template SubDomain<id>::TypeTag;
 
   56    template<std::
size_t id> 
using GridView = 
typename GridGeometry<id>::GridView;
 
   57    template<std::
size_t id> 
using Element = 
typename GridView<id>::template Codim<0>::Entity;
 
   58    template<std::
size_t id> 
using FVElementGeometry = 
typename GridGeometry<id>::LocalView;
 
   59    template<std::
size_t id> 
using SubControlVolumeFace = 
typename FVElementGeometry<id>::SubControlVolumeFace;
 
   60    template<std::
size_t id> 
using SubControlVolume = 
typename FVElementGeometry<id>::SubControlVolume;
 
   61    using CouplingStencil = std::vector<std::size_t>;
 
   63    template<std::
size_t id>
 
   64    using SubCouplingManagerT = 
typename std::tuple_element_t<id, std::tuple<CouplingMgrs...>>;
 
   66    using CMIndices = std::make_index_sequence<
sizeof...(CouplingMgrs)>;
 
   69    template<std::
size_t id>
 
   70    using SubSolutionVector = std::decay_t<decltype(std::declval<typename MDTraits::SolutionVector>()[Dune::index_constant<id>()])>;
 
   71    using SolutionVectors = 
typename MDTraits::template TupleOfSharedPtr<SubSolutionVector>;
 
   73    static constexpr auto couplingManagerMap_ = CouplingMap::managerMap();
 
   76    template<std::
size_t i, std::
size_t j>
 
   77    static constexpr auto globalToLocal_(Dune::index_constant<i> domainI, Dune::index_constant<j> domainJ)
 
   79        static_assert(i <= MDTraits::numSubDomains && j <= MDTraits::numSubDomains);
 
   80        return CouplingMap::globalToLocal(domainI, domainJ);
 
   84    template<
class Map, std::
size_t i, std::
size_t j>
 
   85    static constexpr bool isCoupled_(Dune::index_constant<i> domainI, Dune::index_constant<j>)
 
   86    { 
return Detail::HasIndex<j, std::decay_t<
decltype(Map::coupledDomains(domainI))>>::value; }
 
   89    template<std::
size_t i, std::
size_t j>
 
   90    static constexpr auto subCouplingManagerIndex_(Dune::index_constant<i> domainI, Dune::index_constant<j> domainJ)
 
   93            isCoupled_<CouplingMap>(domainI, domainJ),
 
   94            "Sub-coupling manager only exists for coupled domains." 
   96        return couplingManagerMap_[i][j];
 
  100    template<std::
size_t i, std::
size_t j>
 
  105        using namespace Dune::Hybrid;
 
  106        forEach(couplingManagers_, [&](
auto&& couplingManager)
 
  108            couplingManager = std::make_shared<
typename std::decay_t<
decltype(couplingManager)>::element_type>();
 
  111        forEach(solutionVectors_, [&](
auto&& solutionVector)
 
  113            solutionVector = std::make_shared<
typename std::decay_t<
decltype(solutionVector)>::element_type>();
 
 
  118    template<std::
size_t i, std::
size_t j>
 
  120                             Dune::index_constant<j> domainJ)
 
  122        constexpr auto idx = subCouplingManagerIndex_(domainI, domainJ);
 
  123        return *std::get<idx>(couplingManagers_);
 
 
  127    template<std::
size_t i, std::
size_t j>
 
  129                                   Dune::index_constant<j> domainJ)
 const 
  131        constexpr auto idx = subCouplingManagerIndex_(domainI, domainJ);
 
  132        return *std::get<idx>(couplingManagers_);
 
 
  136    template<std::
size_t i, std::
size_t j, 
class Apply>
 
  137    decltype(
auto) 
subApply(Dune::index_constant<i> domainI,
 
  138                            Dune::index_constant<j> domainJ,
 
  141        constexpr auto localIndices = globalToLocal_(domainI, domainJ);
 
  142        return apply(
subCouplingManager(domainI, domainJ), localIndices.first, localIndices.second);
 
 
  146    template<std::
size_t i, std::
size_t j, 
class Apply>
 
  147    decltype(
auto) 
subApply(Dune::index_constant<i> domainI,
 
  148                            Dune::index_constant<j> domainJ,
 
  149                            const Apply& apply) 
const 
  151        constexpr auto localIndices = globalToLocal_(domainI, domainJ);
 
  152        return apply(
subCouplingManager(domainI, domainJ), localIndices.first, localIndices.second);
 
 
  156    template<std::
size_t i, 
class Apply>
 
  157    decltype(
auto) 
subApply(Dune::index_constant<i> domainI, Apply&& apply)
 
  159        constexpr auto dm = CouplingMap::coupledDomains(domainI);
 
  160        static_assert(std::tuple_size_v<std::decay_t<
decltype(dm)>> != 0, 
"subApply on uncoupled domain!");
 
  161        constexpr auto domainJ = std::get<0>(dm);
 
  162        constexpr auto localIndices = globalToLocal_(domainI, domainJ);
 
 
  167    template<std::
size_t i, 
class Apply>
 
  168    decltype(
auto) 
subApply(Dune::index_constant<i> domainI, 
const Apply& apply) 
const 
  170        constexpr auto dm = CouplingMap::coupledDomains(domainI);
 
  171        static_assert(std::tuple_size_v<std::decay_t<
decltype(dm)>> != 0, 
"subApply on uncoupled domain!");
 
  172        constexpr auto domainJ = std::get<0>(dm);
 
  173        constexpr auto localIndices = globalToLocal_(domainI, domainJ);
 
 
  180        using namespace Dune::Hybrid;
 
  181        forEach(integralRange(Dune::Hybrid::size(solutionVectors_)), [&](
const auto id)
 
  183            *std::get<id>(solutionVectors_) = 
curSol[id];
 
 
  195    template<std::
size_t id, 
class JacobianPattern>
 
  202    template<std::
size_t i, 
class Entity, std::
size_t j>
 
  204                                const Entity& entity,
 
  205                                Dune::index_constant<j> domainJ)
 const 
  208        if constexpr (isCoupled_<CouplingMap>(domainI, domainJ))
 
  209            return subApply(domainI, domainJ, [&](
const auto& cm, 
auto&& ii, 
auto&& jj) -> 
const auto& {
 
  210                return cm.couplingStencil(ii, entity, jj);
 
  213            return emptyStencil_;
 
 
  218    template<std::
size_t i, 
class LocalAssemblerI, std::
size_t j>
 
  220                                        const SubControlVolumeFace<i>& scvfI,
 
  221                                        const LocalAssemblerI& localAssemblerI,
 
  222                                        Dune::index_constant<j> domainJ,
 
  223                                        std::size_t dofIdxGlobalJ) 
const 
  225        if constexpr (i == j || isCoupled_<CouplingMap>(domainI, domainJ))
 
  226            return subApply(domainI, domainJ, [&](
const auto& cm, 
auto&& ii, 
auto&& jj) -> 
decltype(
auto) {
 
  227                return cm.evalCouplingResidual(ii, scvfI, localAssemblerI, jj, dofIdxGlobalJ);
 
  231            DUNE_THROW(Dune::InvalidStateException,
 
  232                "Calling evalCouplingResidual for uncoupled domains " << i << 
" and " << j
 
  234            return localAssemblerI.evalLocalResidual();
 
 
  240    template<std::
size_t i, 
class LocalAssemblerI, std::
size_t j>
 
  242                                        const LocalAssemblerI& localAssemblerI,
 
  243                                        Dune::index_constant<j> domainJ,
 
  244                                        std::size_t dofIdxGlobalJ) 
const 
  246        if constexpr (i == j || isCoupled_<CouplingMap>(domainI, domainJ))
 
  247            return subApply(domainI, domainJ, [&](
const auto& cm, 
auto&& ii, 
auto&& jj) -> 
decltype(
auto) {
 
  248                return cm.evalCouplingResidual(ii, localAssemblerI, jj, dofIdxGlobalJ);
 
  252            DUNE_THROW(Dune::InvalidStateException,
 
  253                "Calling evalCouplingResidual for uncoupled domains " << i << 
" and " << j
 
  255            return localAssemblerI.evalLocalResidual();
 
 
  261    template<std::
size_t i, 
class LocalAssemblerI, std::
size_t j>
 
  263                                        const LocalAssemblerI& localAssemblerI,
 
  264                                        const SubControlVolume<i>& scvI,
 
  265                                        Dune::index_constant<j> domainJ,
 
  266                                        std::size_t dofIdxGlobalJ) 
const 
  268        if constexpr (i == j || isCoupled_<CouplingMap>(domainI, domainJ))
 
  269            return subApply(domainI, domainJ, [&](
const auto& cm, 
auto&& ii, 
auto&& jj) -> 
decltype(
auto) {
 
  270                return cm.evalCouplingResidual(ii, localAssemblerI, scvI, jj, dofIdxGlobalJ);
 
  274            DUNE_THROW(Dune::InvalidStateException,
 
  275                "Calling evalCouplingResidual for uncoupled domains " << i << 
" and " << j
 
  277            return localAssemblerI.evalLocalResidual();
 
 
  284    template<std::
size_t i, 
class LocalAssemblerI, std::
size_t j, 
class PrimaryVariables>
 
  286                               const LocalAssemblerI& localAssemblerI,
 
  287                               Dune::index_constant<j> domainJ,
 
  288                               const std::size_t dofIdxGlobalJ,
 
  289                               const PrimaryVariables& priVars,
 
  293        if constexpr (i != j)
 
  295            if constexpr (isCoupled_<CouplingMap>(domainI, domainJ))
 
  296                subApply(domainI, domainJ, [&](
auto& cm, 
auto&& ii, 
auto&& jj){
 
  297                    cm.updateCouplingContext(ii, localAssemblerI, jj, dofIdxGlobalJ, priVars, pvIdxJ);
 
  304            using namespace Dune::Hybrid;
 
  305            forEach(CouplingMap::coupledDomains(domainI), [&](
const auto domainJ){
 
  306                static_assert(domainI != domainJ);
 
  307                subApply(domainI, domainJ, [&](
auto& cm, 
auto&& ii, 
auto&& jj){
 
  308                    cm.updateCouplingContext(ii, localAssemblerI, ii, dofIdxGlobalJ, priVars, pvIdxJ);
 
 
  315    template<std::
size_t i, 
class Assembler = 
int>
 
  316    void bindCouplingContext(Dune::index_constant<i> domainI, 
const Element<i>& element, 
const Assembler& assembler = 0)
 
  319        using namespace Dune::Hybrid;
 
  320        forEach(CouplingMap::coupledDomains(domainI), [&](
const auto domainJ){
 
  321            subApply(domainI, domainJ, [&](
auto& cm, 
auto&& ii, 
auto&& jj) -> 
void {
 
  322                cm.bindCouplingContext(ii, element, assembler);
 
 
  331    template<std::
size_t i>
 
  333                                  const std::string& paramGroup) 
const 
  335        return subApply(domainI, [&](
const auto& cm, 
auto&& ii) -> 
decltype(
auto) {
 
  336            return cm.numericEpsilon(ii, paramGroup);
 
 
  346    template<std::
size_t i, 
class LocalAssemblerI, 
class JacobianMatrixDiagBlock, 
class Gr
idVariables>
 
  348                                         const LocalAssemblerI& localAssemblerI,
 
  349                                         const typename LocalAssemblerI::LocalResidual::ElementResidualVector& origResiduals,
 
  350                                         JacobianMatrixDiagBlock& A,
 
  351                                         GridVariables& gridVariables)
 
 
  354    template<std::
size_t i, 
class LocalAssemblerI, 
class UpdatableElementVolVars, 
class UpdatableFluxVarCache>
 
  356                                const LocalAssemblerI& localAssemblerI,
 
  357                                UpdatableElementVolVars& elemVolVars,
 
  358                                UpdatableFluxVarCache& elemFluxVarsCache)
 
  361        using namespace Dune::Hybrid;
 
  362        forEach(CouplingMap::coupledDomains(domainI), [&](
const auto domainJ){
 
  363            subApply(domainI, domainJ, [&](
auto& cm, 
auto&& ii, 
auto&& jj){
 
  364                cm.updateCoupledVariables(ii, localAssemblerI, elemVolVars, elemFluxVarsCache);
 
 
  371    { 
return solutionVectors_; }
 
 
  374    { 
return solutionVectors_; }
 
 
  377    CouplingManagers couplingManagers_;
 
  378    SolutionVectors solutionVectors_;
 
  380    CouplingStencil emptyStencil_;
 
 
decltype(auto) evalCouplingResidual(Dune::index_constant< i > domainI, const LocalAssemblerI &localAssemblerI, const SubControlVolume< i > &scvI, Dune::index_constant< j > domainJ, std::size_t dofIdxGlobalJ) const
Definition multibinarycouplingmanager.hh:262
decltype(auto) evalCouplingResidual(Dune::index_constant< i > domainI, const LocalAssemblerI &localAssemblerI, Dune::index_constant< j > domainJ, std::size_t dofIdxGlobalJ) const
Definition multibinarycouplingmanager.hh:241
SubCouplingManagerT< couplingManagerMap_[i][j]> SubCouplingManager
Definition multibinarycouplingmanager.hh:101
const auto & couplingStencil(Dune::index_constant< i > domainI, const Entity &entity, Dune::index_constant< j > domainJ) const
Return the coupling element stencil for a given bulk domain element.
Definition multibinarycouplingmanager.hh:203
MultiBinaryCouplingManager()
Definition multibinarycouplingmanager.hh:103
void evalAdditionalDomainDerivatives(Dune::index_constant< i > domainI, const LocalAssemblerI &localAssemblerI, const typename LocalAssemblerI::LocalResidual::ElementResidualVector &origResiduals, JacobianMatrixDiagBlock &A, GridVariables &gridVariables)
evaluate additional derivatives of the element residual of a domain with respect to dofs in the same ...
Definition multibinarycouplingmanager.hh:347
decltype(auto) numericEpsilon(Dune::index_constant< i > domainI, const std::string ¶mGroup) const
return the numeric epsilon used for deflecting primary variables of coupled domain i.
Definition multibinarycouplingmanager.hh:332
decltype(auto) subApply(Dune::index_constant< i > domainI, Dune::index_constant< j > domainJ, Apply &&apply)
apply a function to the domainI-domainJ sub coupling manager using its local indices
Definition multibinarycouplingmanager.hh:137
auto & subCouplingManager(Dune::index_constant< i > domainI, Dune::index_constant< j > domainJ)
return the binary sub-coupling manager
Definition multibinarycouplingmanager.hh:119
void updateCoupledVariables(Dune::index_constant< i > domainI, const LocalAssemblerI &localAssemblerI, UpdatableElementVolVars &elemVolVars, UpdatableFluxVarCache &elemFluxVarsCache)
Definition multibinarycouplingmanager.hh:355
void extendJacobianPattern(Dune::index_constant< id > domainI, JacobianPattern &pattern) const
extend the jacobian pattern of the diagonal block of domain i by those entries that are not already i...
Definition multibinarycouplingmanager.hh:196
decltype(auto) subApply(Dune::index_constant< i > domainI, Apply &&apply)
apply a function to a sub coupling manager containing this domain
Definition multibinarycouplingmanager.hh:157
void bindCouplingContext(Dune::index_constant< i > domainI, const Element< i > &element, const Assembler &assembler=0)
Bind the coupling context for a low dim element TODO remove Assembler.
Definition multibinarycouplingmanager.hh:316
void updateCouplingContext(Dune::index_constant< i > domainI, const LocalAssemblerI &localAssemblerI, Dune::index_constant< j > domainJ, const std::size_t dofIdxGlobalJ, const PrimaryVariables &priVars, int pvIdxJ)
Update the coupling context for the bulk face residual w.r.t to the lowDim dofs.
Definition multibinarycouplingmanager.hh:285
decltype(auto) evalCouplingResidual(Dune::index_constant< i > domainI, const SubControlVolumeFace< i > &scvfI, const LocalAssemblerI &localAssemblerI, Dune::index_constant< j > domainJ, std::size_t dofIdxGlobalJ) const
Definition multibinarycouplingmanager.hh:219
const SolutionVectors & curSol() const
Definition multibinarycouplingmanager.hh:373
decltype(auto) subApply(Dune::index_constant< i > domainI, const Apply &apply) const
apply a function to a sub coupling manager containing this domain
Definition multibinarycouplingmanager.hh:168
SolutionVectors & curSol()
Definition multibinarycouplingmanager.hh:370
void updateSolution(const typename MDTraits::SolutionVector &curSol)
Update the solution vector before assembly.
Definition multibinarycouplingmanager.hh:178
const auto & subCouplingManager(Dune::index_constant< i > domainI, Dune::index_constant< j > domainJ) const
return the binary sub-coupling manager
Definition multibinarycouplingmanager.hh:128
decltype(auto) subApply(Dune::index_constant< i > domainI, Dune::index_constant< j > domainJ, const Apply &apply) const
apply a function to the domainI-domainJ sub coupling manager using its local indices
Definition multibinarycouplingmanager.hh:147
Defines all properties used in Dumux.
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition propertysystem.hh:296
Traits for multidomain problems.
Distance implementation details.
Definition cvfelocalresidual.hh:25
Definition multibinarycouplingmanager.hh:27
typename makeFromIndexedType< std::tuple, PtrType, Indices >::type type
Definition multidomain/traits.hh:79