From dcddffd082ee86f3b013e0c9392c2949702abecb Mon Sep 17 00:00:00 2001 From: Kilian Weishaupt <kilian.weishaupt@iws.uni-stuttgart.de> Date: Mon, 29 Jun 2020 17:41:39 +0200 Subject: [PATCH] [md][cclocalassembler] Enable internal Dirichlet constraints --- .../multidomain/subdomaincclocalassembler.hh | 148 ++++++++++++++++-- 1 file changed, 136 insertions(+), 12 deletions(-) diff --git a/dumux/multidomain/subdomaincclocalassembler.hh b/dumux/multidomain/subdomaincclocalassembler.hh index 60eb4e8ac4..a4657ac225 100644 --- a/dumux/multidomain/subdomaincclocalassembler.hh +++ b/dumux/multidomain/subdomaincclocalassembler.hh @@ -84,8 +84,6 @@ class SubDomainCCLocalAssemblerBase : public FVLocalAssemblerBase<TypeTag, Assem using CouplingManager = typename Assembler::CouplingManager; using ElementResidualVector = typename ParentType::LocalResidual::ElementResidualVector; - static_assert(!Problem::enableInternalDirichletConstraints(), "Internal Dirichlet constraints are currently not implemented for cc-methods!"); - public: //! export the domain id of this sub-domain static constexpr auto domainId = typename Dune::index_constant<id>(); @@ -282,6 +280,7 @@ class SubDomainCCLocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, /*i { using ThisType = SubDomainCCLocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, /*implicit=*/true>; using ParentType = SubDomainCCLocalAssemblerBase<id, TypeTag, Assembler, ThisType, /*implicit=*/true>; + using Problem = GetPropType<TypeTag, Properties::Problem>; using Scalar = GetPropType<TypeTag, Properties::Scalar>; using LocalResidualValues = GetPropType<TypeTag, Properties::NumEqVector>; @@ -406,15 +405,54 @@ public: eps_(elemSol[0][pvIdx], pvIdx), numDiffMethod); // add the current partial derivatives to the global jacobian matrix - for (int eqIdx = 0; eqIdx < numEq; eqIdx++) + if constexpr (Problem::enableInternalDirichletConstraints()) { - // the diagonal entries - A[globalI][globalI][eqIdx][pvIdx] += partialDerivs[0][eqIdx]; + // check if own element has internal Dirichlet constraint + const auto internalDirichletConstraintsOwnElement = this->problem().hasInternalDirichletConstraint(this->element(), scv); + const auto dirichletValues = this->problem().internalDirichlet(this->element(), scv); + + for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) + { + if (internalDirichletConstraintsOwnElement[eqIdx]) + { + origResiduals[0][eqIdx] = this->curElemVolVars()[scv].priVars()[eqIdx] - dirichletValues[eqIdx]; + A[globalI][globalI][eqIdx][pvIdx] = (eqIdx == pvIdx) ? 1.0 : 0.0; + } + else + A[globalI][globalI][eqIdx][pvIdx] += partialDerivs[0][eqIdx]; + } // off-diagonal entries j = 1; for (const auto& dataJ : connectivityMap[globalI]) - A[dataJ.globalJ][globalI][eqIdx][pvIdx] += partialDerivs[j++][eqIdx]; + { + const auto& neighborElement = neighborElements[j-1]; + const auto& neighborScv = fvGeometry.scv(dataJ.globalJ); + const auto internalDirichletConstraintsNeighbor = this->problem().hasInternalDirichletConstraint(neighborElement, neighborScv); + + for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) + { + if (internalDirichletConstraintsNeighbor[eqIdx]) + A[dataJ.globalJ][globalI][eqIdx][pvIdx] = 0.0; + else + A[dataJ.globalJ][globalI][eqIdx][pvIdx] += partialDerivs[j][eqIdx]; + } + + ++j; + } + } + else // no internal Dirichlet constraints specified + { + for (int eqIdx = 0; eqIdx < numEq; eqIdx++) + { + // the diagonal entries + A[globalI][globalI][eqIdx][pvIdx] += partialDerivs[0][eqIdx]; + + // off-diagonal entries + j = 1; + for (const auto& dataJ : connectivityMap[globalI]) + A[dataJ.globalJ][globalI][eqIdx][pvIdx] += partialDerivs[j++][eqIdx]; + } } // restore the original state of the scv's volume variables @@ -526,8 +564,31 @@ public: epsCoupl(priVarsJ[pvIdx], pvIdx), numDiffMethod); // add the current partial derivatives to the global jacobian matrix - for (int eqIdx = 0; eqIdx < numEq; eqIdx++) - A[globalI][globalJ][eqIdx][pvIdx] += partialDeriv[eqIdx]; + if constexpr (Problem::enableInternalDirichletConstraints()) + { + const auto& scv = fvGeometry.scv(globalI); + const auto internalDirichletConstraints = this->problem().hasInternalDirichletConstraint(this->element(), scv); + if (internalDirichletConstraints.none()) + { + for (int eqIdx = 0; eqIdx < numEq; eqIdx++) + A[globalI][globalJ][eqIdx][pvIdx] += partialDeriv[eqIdx]; + } + else + { + for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) + { + if (internalDirichletConstraints[eqIdx]) + A[globalI][globalJ][eqIdx][pvIdx] = 0.0; + else + A[globalI][globalJ][eqIdx][pvIdx] += partialDeriv[eqIdx]; + } + } + } + else + { + for (int eqIdx = 0; eqIdx < numEq; eqIdx++) + A[globalI][globalJ][eqIdx][pvIdx] += partialDeriv[eqIdx]; + } // restore the current element solution priVarsJ[pvIdx] = origPriVarsJ[pvIdx]; @@ -560,6 +621,7 @@ class SubDomainCCLocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, /*i using Scalar = GetPropType<TypeTag, Properties::Scalar>; using LocalResidualValues = GetPropType<TypeTag, Properties::NumEqVector>; + using Problem = GetPropType<TypeTag, Properties::Problem>; static constexpr int numEq = GetPropType<TypeTag, Properties::ModelTraits>::numEq(); static constexpr auto domainI = Dune::index_constant<id>(); @@ -645,8 +707,28 @@ public: // add the current partial derivatives to the global jacobian matrix // only diagonal entries for explicit jacobians - for (int eqIdx = 0; eqIdx < numEq; eqIdx++) - A[globalI][globalI][eqIdx][pvIdx] += partialDeriv[eqIdx]; + if constexpr (Problem::enableInternalDirichletConstraints()) + { + // check if own element has internal Dirichlet constraint + const auto internalDirichletConstraints = this->problem().hasInternalDirichletConstraint(this->element(), scv); + const auto dirichletValues = this->problem().internalDirichlet(this->element(), scv); + + for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) + { + if (internalDirichletConstraints[eqIdx]) + { + residual[eqIdx] = this->curElemVolVars()[scv].priVars()[eqIdx] - dirichletValues[eqIdx]; + A[globalI][globalI][eqIdx][pvIdx] = (eqIdx == pvIdx) ? 1.0 : 0.0; + } + else + A[globalI][globalI][eqIdx][pvIdx] += partialDeriv[eqIdx]; + } + } + else + { + for (int eqIdx = 0; eqIdx < numEq; eqIdx++) + A[globalI][globalI][eqIdx][pvIdx] += partialDeriv[eqIdx]; + } // restore the original state of the scv's volume variables curVolVars = origVolVars; @@ -687,6 +769,7 @@ class SubDomainCCLocalAssembler<id, TypeTag, Assembler, DiffMethod::analytic, /* using LocalResidualValues = GetPropType<TypeTag, Properties::NumEqVector>; using GridView = typename GetPropType<TypeTag, Properties::GridGeometry>::GridView; using Element = typename GridView::template Codim<0>::Entity; + using Problem = GetPropType<TypeTag, Properties::Problem>; enum { numEq = GetPropType<TypeTag, Properties::ModelTraits>::numEq() }; enum { dim = GridView::dimension }; @@ -749,8 +832,35 @@ public: } } - // return element residual - return this->evalLocalResidual()[0]; + if constexpr (Problem::enableInternalDirichletConstraints()) + { + // check if own element has internal Dirichlet constraint + const auto internalDirichletConstraints = this->problem().hasInternalDirichletConstraint(this->element(), scv); + const auto dirichletValues = this->problem().internalDirichlet(this->element(), scv); + + auto residual = this->evalLocalResidual()[0]; + + for (int pvIdx = 0; pvIdx < numEq; ++pvIdx) + { + for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) + { + if (internalDirichletConstraints[eqIdx]) + { + residual[eqIdx] = this->curElemVolVars()[scv].priVars()[eqIdx] - dirichletValues[eqIdx]; + A[globalI][globalI][eqIdx][pvIdx] = (eqIdx == pvIdx) ? 1.0 : 0.0; + + // inner faces + for (const auto& scvf : scvfs(fvGeometry)) + if (!scvf.boundary()) + A[globalI][fvGeometry.scv(scvf.outsideScvIdx()).dofIndex()][eqIdx][pvIdx] = 0.0; + } + } + } + return residual; + } + else + // return element residual + return this->evalLocalResidual()[0]; } /*! @@ -782,6 +892,20 @@ public: { const auto& elementJ = this->assembler().gridGeometry(domainJ).element(globalJ); this->couplingManager().addCouplingDerivatives(A[globalI][globalJ], domainI, element, fvGeometry, curElemVolVars, domainJ, elementJ); + + // add the current partial derivatives to the global jacobian matrix + if constexpr (Problem::enableInternalDirichletConstraints()) + { + const auto& scv = fvGeometry.scv(globalI); + const auto internalDirichletConstraints = this->problem().hasInternalDirichletConstraint(this->element(), scv); + if (internalDirichletConstraints.any()) + { + for (int pvIdx = 0; pvIdx < numEq; ++pvIdx) + for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) + if (internalDirichletConstraints[eqIdx]) + A[globalI][globalJ][eqIdx][pvIdx] = 0.0; + } + } } } }; -- GitLab