GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: /builds/dumux-repositories/dumux/dumux/multidomain/dualnetwork/extendedsourcestencil.hh
Date: 2024-09-21 20:52:54
Exec Total Coverage
Lines: 33 37 89.2%
Functions: 4 4 100.0%
Branches: 41 58 70.7%

Line Branch Exec Source
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 // SPDX-FileCopyrightInfo: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5 // SPDX-License-Identifier: GPL-3.0-or-later
6 //
7 /*!
8 * \file
9 * \ingroup DualNetworkCoupling
10 * \ingroup PoreNetworkModels
11 * \brief Extended source stencil helper class for coupling managers
12 */
13
14 #ifndef DUMUX_DUAL_NETWORK_EXTENDEDSOURCESTENCIL_HH
15 #define DUMUX_DUAL_NETWORK_EXTENDEDSOURCESTENCIL_HH
16
17 #include <vector>
18
19 #include <dune/common/indices.hh>
20
21 #include <dumux/common/properties.hh>
22 #include <dumux/common/parameters.hh>
23 #include <dumux/common/numericdifferentiation.hh>
24 #include <dumux/discretization/method.hh>
25
26 namespace Dumux::PoreNetwork {
27
28 /*!
29 * \ingroup DualNetworkCoupling
30 * \ingroup PoreNetworkModels
31 * \brief A class managing an extended source stencil
32 * \tparam CouplingManager the coupling manager type
33 */
34 template<class CouplingManager>
35 class PNMHeatExtendedSourceStencil
36 {
37 using MDTraits = typename CouplingManager::MultiDomainTraits;
38 using Scalar = typename MDTraits::Scalar;
39
40 template<std::size_t id> using SubDomainTypeTag = typename MDTraits::template SubDomain<id>::TypeTag;
41 template<std::size_t id> using GridGeometry = GetPropType<SubDomainTypeTag<id>, Properties::GridGeometry>;
42 template<std::size_t id> using GridView = typename GridGeometry<id>::GridView;
43 template<std::size_t id> using Element = typename GridView<id>::template Codim<0>::Entity;
44
45 static constexpr auto solidDomainIdx = CouplingManager::solidDomainIdx;
46 static constexpr auto voidDomainIdx = CouplingManager::voidDomainIdx;
47
48 template<std::size_t id>
49 static constexpr bool isBox()
50 { return GridGeometry<id>::discMethod == DiscretizationMethods::box; }
51 public:
52 /*!
53 * \brief extend the jacobian pattern of the diagonal block of domain i
54 * by those entries that are not already in the uncoupled pattern
55 * \note Such additional dependencies can arise from the coupling, e.g. if a coupling source
56 * term depends on a non-local average of a quantity of the same domain
57 */
58 template<std::size_t id, class JacobianPattern>
59 4 void extendJacobianPattern(const CouplingManager& couplingManager, Dune::index_constant<id> domainI, JacobianPattern& pattern) const
60 {
61 // add additional dof dependencies
62
4/4
✓ Branch 2 taken 3191 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 3191 times.
✓ Branch 5 taken 2 times.
6390 for (const auto& element : elements(couplingManager.gridView(domainI)))
63 {
64 10750 const auto& dofs = extendedSourceStencil_(couplingManager, domainI, element);
65 if constexpr (isBox<domainI>())
66 {
67
4/4
✓ Branch 0 taken 6382 times.
✓ Branch 1 taken 3191 times.
✓ Branch 2 taken 6382 times.
✓ Branch 3 taken 3191 times.
25528 for (int i = 0; i < element.subEntities(GridView<domainI>::dimension); ++i)
68
4/4
✓ Branch 0 taken 17572 times.
✓ Branch 1 taken 6382 times.
✓ Branch 2 taken 17572 times.
✓ Branch 3 taken 6382 times.
108580 for (const auto globalJ : dofs)
69
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17572 times.
35144 pattern.add(couplingManager.problem(domainI).gridGeometry().vertexMapper().subIndex(element, i, GridView<domainI>::dimension), globalJ);
70 }
71 else
72 {
73 const auto globalI = couplingManager.problem(domainI).gridGeometry().elementMapper().index(element);
74 for (const auto globalJ : dofs)
75 pattern.add(globalI, globalJ);
76 }
77 }
78 4 }
79
80 /*!
81 * \brief evaluate additional derivatives of the element residual of a domain with respect
82 * to dofs in the same domain that are not in the regular stencil (per default this is not the case)
83 * \note Such additional dependencies can arise from the coupling, e.g. if a coupling source
84 * term depends on a non-local average of a quantity of the same domain
85 * \note This is the same for box and cc
86 */
87 template<std::size_t i, class LocalAssemblerI, class SolutionVector, class JacobianMatrixDiagBlock, class GridVariables> //TODO edit function s.t. curSol from couplingmanager is used like in dumux/dumux/multidomain/embedded/extendedsourcestencil.hh (commit 3257876)
88 25528 void evalAdditionalDomainDerivatives(CouplingManager& couplingManager,
89 Dune::index_constant<i> domainI,
90 const LocalAssemblerI& localAssemblerI,
91 const SolutionVector& curSol,
92 JacobianMatrixDiagBlock& A,
93 GridVariables& gridVariables) const
94 {
95 // const auto& curSolI = couplingManager.curSol(domainI); //TODO:curSol declared protected in .../dumux/dumux/multidomain/couplingmanager.hh
96 25528 const auto& curSolI = curSol;
97 25528 constexpr auto numEq = std::decay_t<decltype(curSolI[0])>::size();
98 25528 const auto& elementI = localAssemblerI.element();
99
100 // only do something if we have an extended stencil
101
3/5
✓ Branch 0 taken 8736 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4028 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4028 times.
25528 if (extendedSourceStencil_(couplingManager, domainI, elementI).empty())
102 17472 return;
103
104 // compute the undeflected residual (source only!)
105 8056 const auto origResidual = localAssemblerI.evalLocalSourceResidual(elementI);
106
107 // compute derivate for all additional dofs in the circle stencil
108
4/5
✗ Branch 0 not taken.
✓ Branch 1 taken 35144 times.
✓ Branch 2 taken 4028 times.
✓ Branch 3 taken 35144 times.
✓ Branch 4 taken 4028 times.
78344 for (const auto dofIndex : extendedSourceStencil_(couplingManager, domainI, elementI))
109 {
110 // std::cout << "deflecting " << dofIndex << std::endl;
111 70288 auto partialDerivs = origResidual;
112 70288 const auto origPriVars = curSolI[dofIndex];
113
114 // calculate derivatives w.r.t to the privars at the dof at hand
115
2/2
✓ Branch 0 taken 70288 times.
✓ Branch 1 taken 35144 times.
210864 for (int pvIdx = 0; pvIdx < numEq; pvIdx++)
116 {
117 // reset partial derivatives
118 140576 partialDerivs = 0.0;
119
120 281152 auto evalResiduals = [&](Scalar priVar)
121 {
122 // update the coupling context (solution vector and recompute element residual)
123 70288 auto priVars = origPriVars;
124 70288 priVars[pvIdx] = priVar;
125 70288 couplingManager.updateCouplingContext(domainI, localAssemblerI, domainI, dofIndex, priVars, pvIdx);
126 70288 return localAssemblerI.evalLocalSourceResidual(elementI);
127 };
128
129 // derive the residuals numerically
130
4/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 70287 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
140576 static const int numDiffMethod = getParam<int>("Assembly.NumericDifferenceMethod");
131
3/6
✓ Branch 1 taken 70288 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 70288 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 70288 times.
✗ Branch 8 not taken.
421728 NumericDifferentiation::partialDerivative(evalResiduals, curSolI[dofIndex][pvIdx],
132 partialDerivs, origResidual, numDiffMethod); //TODO: maybe change like in dumux/dumux/md/embedded/extendedsourcestencil.hh line 142
133
134 // update the global stiffness matrix with the current partial derivatives
135
2/2
✓ Branch 0 taken 140576 times.
✓ Branch 1 taken 70288 times.
702880 for (const auto& scvJ : scvs(localAssemblerI.fvGeometry()))
136 {
137
2/2
✓ Branch 0 taken 281152 times.
✓ Branch 1 taken 140576 times.
843456 for (int eqIdx = 0; eqIdx < numEq; eqIdx++)
138 {
139 // A[i][col][eqIdx][pvIdx] is the rate of change of
140 // the residual of equation 'eqIdx' at dof 'i'
141 // depending on the primary variable 'pvIdx' at dof
142 // 'col'.
143 // std::cout << "Adding " << partialDerivs[scvJ.indexInElement()][eqIdx] << ", pvIdx " << pvIdx << std::endl;
144
4/8
✓ Branch 1 taken 281152 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 281152 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 281152 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 281152 times.
✗ Branch 11 not taken.
2249216 A[scvJ.dofIndex()][dofIndex][eqIdx][pvIdx] += partialDerivs[scvJ.indexInElement()][eqIdx];
145 }
146 }
147
148 // restore the original coupling context
149
1/2
✓ Branch 1 taken 70288 times.
✗ Branch 2 not taken.
140576 couplingManager.updateCouplingContext(domainI, localAssemblerI, domainI, dofIndex, origPriVars, pvIdx);
150 }
151 }
152 }
153
154 //! clear the internal data
155 1 void clear() { sourceStencils_.clear(); }
156
157 //! return a reference to the stencil
158 auto& stencil()
159
1/2
✓ Branch 1 taken 9632 times.
✗ Branch 2 not taken.
10639 { return sourceStencils_; }
160
161 private:
162 //! the extended source stencil due to the source average (always empty for lowdim, but may be filled for bulk)
163 template<std::size_t id>
164 const auto& extendedSourceStencil_(const CouplingManager& couplingManager, Dune::index_constant<id> domainId, const Element<id>& element) const
165 {
166 if constexpr (domainId == voidDomainIdx)
167 {
168 const auto voidElementIdx = couplingManager.problem(voidDomainIdx).gridGeometry().elementMapper().index(element);
169 if (sourceStencils_.count(voidElementIdx))
170 return sourceStencils_.at(voidElementIdx);
171 }
172
173
2/4
✓ Branch 0 taken 8736 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8736 times.
✗ Branch 3 not taken.
21840 return couplingManager.emptyStencil(domainId);
174 }
175
176 //! the additional stencil for the kernel evaluations / circle averages
177 std::unordered_map<std::size_t, std::vector<std::size_t>> sourceStencils_;
178 };
179
180 } // end namespace Dumux::PoreNetwork
181
182 #endif
183