version 3.8.0
Loading...
Searching...
No Matches
multidomain/dualnetwork/couplingmanager.hh
Go to the documentation of this file.
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//
14#ifndef DUMUX_MULTIDOMAIN_DUAL_NETWORK_COUPLINGMANAGER_HH
15#define DUMUX_MULTIDOMAIN_DUAL_NETWORK_COUPLINGMANAGER_HH
16
17#include <iostream>
18#include <vector>
19#include <tuple>
20
21#include <dune/common/indices.hh>
22#include <dune/common/exceptions.hh>
23#include <dune/common/reservedvector.hh>
24
26#include <dumux/common/math.hh>
34
35#include "couplingmapper.hh"
36
37namespace Dumux::PoreNetwork {
38
45template<class MDTraits>
47: public CouplingManager<MDTraits>
48{
51
52 using Scalar = typename MDTraits::Scalar;
53 using SolutionVector = typename MDTraits::SolutionVector;
54
55 template<std::size_t i> using SubDomainTypeTag = typename MDTraits::template SubDomain<i>::TypeTag;
56 template<std::size_t i> using Problem = GetPropType<SubDomainTypeTag<i>, Properties::Problem>;
57 template<std::size_t i> using PrimaryVariables = GetPropType<SubDomainTypeTag<i>, Properties::PrimaryVariables>;
58 template<std::size_t i> using NumEqVector = Dumux::NumEqVector<PrimaryVariables<i>>;
59 template<std::size_t i> using GridVolumeVariables = GetPropType<SubDomainTypeTag<i>, Properties::GridVolumeVariables>;
60 template<std::size_t i> using ElementVolumeVariables = typename GridVolumeVariables<i>::LocalView;
61 template<std::size_t i> using ElementFluxVariablesCache = typename GetPropType<SubDomainTypeTag<i>, Properties::GridFluxVariablesCache>::LocalView;
62 template<std::size_t i> using VolumeVariables = typename GridVolumeVariables<i>::VolumeVariables;
63 template<std::size_t i> using GridGeometry = typename MDTraits::template SubDomain<i>::GridGeometry;
64 template<std::size_t i> using FVElementGeometry = typename GridGeometry<i>::LocalView;
65 template<std::size_t i> using SubControlVolumeFace = typename GridGeometry<i>::SubControlVolumeFace;
66 template<std::size_t i> using SubControlVolume = typename GridGeometry<i>::SubControlVolume;
67 template<std::size_t i> using GridView = typename GridGeometry<i>::GridView;
68 template<std::size_t i> using Element = typename GridView<i>::template Codim<0>::Entity;
69 template<std::size_t i> using Indices = typename GetPropType<SubDomainTypeTag<i>, Properties::ModelTraits>::Indices;
70
71 template<std::size_t id> using GridVariables = typename MDTraits::template SubDomain<id>::GridVariables;
72 using GridVariablesTuple = typename MDTraits::template TupleOfSharedPtr<GridVariables>;
73
75
76 template<std::size_t i>
77 static constexpr auto domainIdx()
78 { return typename MDTraits::template SubDomain<i>::Index{}; }
79
80 using CouplingStencil = std::vector<std::size_t>;
82
83
84public:
85 static constexpr auto solidDomainIdx = typename MDTraits::template SubDomain<0>::Index();
86 static constexpr auto voidDomainIdx = typename MDTraits::template SubDomain<1>::Index();
87
88private:
89
90 using VoidElementSolution = std::decay_t<decltype(elementSolution(std::declval<Element<voidDomainIdx>>(), std::declval<SolutionVector>()[voidDomainIdx], std::declval<GridGeometry<voidDomainIdx>>()))>;
91 using SolidElementSolution = std::decay_t<decltype(elementSolution(std::declval<Element<solidDomainIdx>>(), std::declval<SolutionVector>()[solidDomainIdx], std::declval<GridGeometry<solidDomainIdx>>()))>;
92
93 struct CouplingContextForOneConnection
94 {
95 std::size_t connectionGlobalId;
96 std::vector<FVElementGeometry<solidDomainIdx>> solidFVGeometry; // only one needed, but FVElementGeometry can't be default constructed
97 VolumeVariables<solidDomainIdx> solidVolVars;
98 std::vector<FVElementGeometry<voidDomainIdx>> voidFVGeometry;
99 std::vector<ElementVolumeVariables<voidDomainIdx>> voidElemVolVars;
100 std::vector<ElementFluxVariablesCache<voidDomainIdx>> voidElemFluxVarsCache;
101 };
102
103 using CouplingContextForOnePore = std::pair<std::size_t, std::vector<CouplingContextForOneConnection>>;
104 using CouplingContextForOneElement = Dune::ReservedVector<CouplingContextForOnePore, 2>;
105
106 struct ElementCouplingContext
107 {
108 std::size_t boundElementIndex() const
109 { return boundElementIndex_; }
110
111 std::size_t boundDomainId() const
112 { return domaindId_; }
113
114 auto& data()
115 { return data_; }
116
117 template<std::size_t i>
118 void bind(Dune::index_constant<i> domainI,
119 const Element<i>& element,
120 const ThisType& couplingManager)
121 {
122 // do nothing if context is already bound correctly
123 const auto eIdx = couplingManager.gridGeometry(domainI).elementMapper().index(element);
124 if (domaindId_ == i && boundElementIndex_ == eIdx && initialized_)
125 return;
126
127 // do nothing if the element does not couple at all
128 // (this check is probably more expensive, so we do it after the above one)
129 constexpr auto domainJ = Dune::index_constant<1-i>{};
130 if (couplingManager.couplingStencil(domainI, element, domainJ).empty())
131 return;
132
133 data_.clear();
134
135 // each element has two pores for which we need to bind some connection coupling context
136 for (int localVertexIdx = 0; localVertexIdx < 2; ++localVertexIdx)
137 {
138 const auto vIdx = couplingManager.gridGeometry(domainI).vertexMapper().subIndex(element, localVertexIdx, 1);
139 if (!couplingManager.isCoupledPore(domainI, vIdx))
140 continue;
141
142 initialized_ = true;
143 domaindId_ = i;
144 boundElementIndex_ = eIdx;
145
146 const auto& connections = [&]
147 {
148 if constexpr(domainI == solidDomainIdx)
149 return couplingManager.couplingMapper().solidToVoidConnections(vIdx);
150 else
151 return couplingManager.couplingMapper().voidToSolidConnections(vIdx);
152 }();
153 const auto numConnections = std::distance(connections.begin(), connections.end());
154 assert(numConnections == (domainI == solidDomainIdx ? couplingManager.couplingMapper().solidToVoidConnectionIds().at(vIdx).size() : couplingManager.couplingMapper().voidToSolidConnectionIds().at(vIdx).size()));
155
156 data_.push_back(CouplingContextForOnePore{});
157
158 // iterate over all solid/void connections for the given pore
159 data_.back().first = vIdx;
160 data_.back().second.reserve(numConnections);
161 for (const auto& connection : connections)
162 {
163 CouplingContextForOneConnection context;
164 context.connectionGlobalId = connection.id;
165
166 const auto& solidElement = couplingManager.solidGridGeometry_->element(connection.someSolidElementIdx);
167 auto solidFVGeometry = localView(*couplingManager.solidGridGeometry_);
168 solidFVGeometry.bindElement(solidElement);
169 context.solidFVGeometry.push_back(solidFVGeometry);
170
171 for (const auto& solidScv : scvs(solidFVGeometry))
172 {
173 if (solidScv.dofIndex() == connection.solidVertexIdx)
174 context.solidVolVars = couplingManager.volVars(solidDomainIdx, solidElement, solidScv);
175 }
176
177 auto voidFVGeometry = localView(couplingManager.gridGeometry(voidDomainIdx));
178 auto voidElemVolVars = localView(couplingManager.gridVariables(voidDomainIdx).curGridVolVars());
179 auto voidElemFluxVarsCache = localView(couplingManager.gridVariables(voidDomainIdx).gridFluxVarsCache());
180
181 const auto numConvectionVoidElems = connection.convectionVoidElementIdx.size();
182 context.voidFVGeometry.reserve(numConvectionVoidElems);
183 context.voidElemVolVars.reserve(numConvectionVoidElems);
184 context.voidElemFluxVarsCache.reserve(numConvectionVoidElems);
185 for (const auto voidElemIdx : connection.convectionVoidElementIdx)
186 {
187 const auto voidElem = couplingManager.gridGeometry(voidDomainIdx).element(voidElemIdx);
188 voidFVGeometry.bindElement(voidElem);
189 voidElemVolVars.bindElement(voidElem, voidFVGeometry, couplingManager.curSol(voidDomainIdx));
190 voidElemFluxVarsCache.bindElement(voidElem, voidFVGeometry, voidElemVolVars);
191
192 context.voidFVGeometry.push_back(voidFVGeometry);
193 context.voidElemVolVars.push_back(voidElemVolVars);
194 context.voidElemFluxVarsCache.push_back(voidElemFluxVarsCache);
195 }
196 data_.back().second.push_back(std::move(context));
197 }
198 }
199 }
200
201 const auto& operator[](const std::size_t dofIdx) const
202 {
203 for (const auto& d : data_)
204 {
205 if (d.first == dofIdx)
206 return d.second;
207 }
208 DUNE_THROW(Dune::InvalidStateException, "No connection found");
209 }
210
211 private:
212
213 bool initialized_ = false;
214 std::size_t domaindId_;
215 std::size_t boundElementIndex_;
216 mutable Dune::ReservedVector<CouplingContextForOnePore, 2> data_;
217 };
218
219public:
220
222 using MultiDomainTraits = MDTraits;
224 using CouplingStencils = std::unordered_map<std::size_t, CouplingStencil>;
225
229 // \{
230
231 template<class HostGridView, class HostGridData, class VoidGridView, class SolidGridView>
232 void init(std::shared_ptr<Problem<solidDomainIdx>> solidProblem,
233 std::shared_ptr<Problem<voidDomainIdx>> voidProblem,
234 const HostGridView& hostGridView,
235 const HostGridData& hostGridData,
236 const VoidGridView& voidGridView,
237 const SolidGridView& solidGridView,
238 const SolutionVector& curSol)
239 {
240 voidGridGeometry_ = &voidProblem->gridGeometry();
241 solidGridGeometry_ = &solidProblem->gridGeometry();
242 couplingMapper_ = std::make_unique<CouplingMapper>(hostGridView, hostGridData, voidProblem->gridGeometry(), solidProblem->gridGeometry());
243 this->setSubProblems(std::make_tuple(solidProblem, voidProblem));
244 this->updateSolution(curSol);
245
246 const auto& someVoidElement = voidGridGeometry_->element(0);
247 const auto& someSolidElement = solidGridGeometry_->element(0);
251 }
252
253 // \}
254
258 // \{
259
268 template<std::size_t i, std::size_t j>
269 const CouplingStencil& couplingStencil(Dune::index_constant<i> domainI,
270 const Element<i>& element,
271 Dune::index_constant<j> domainJ) const
272 {
273 const auto eIdx = gridGeometry(domainI).elementMapper().index(element);
274
275 auto getStencils = [this, domainI]() -> const auto&
276 {
278 };
279
280 const auto& stencils = getStencils();
281
282 return (stencils.count(eIdx)) ? stencils.at(eIdx) : emptyStencil_;
283 }
284
288 template<std::size_t i>
289 bool isCoupledPore(Dune::index_constant<i> domainI, const std::size_t dofIdx) const
290 {
291 const auto& isCoupledDof = [&]
292 {
293 if constexpr(domainI == solidDomainIdx)
295 else //voidDomainIdx
297 }();
298 return isCoupledDof[dofIdx];
299 }
300
304 template<std::size_t i>
305 Scalar conductionSource(Dune::index_constant<i> domainI,
306 const Element<i>& element,
307 const FVElementGeometry<i>& fvGeometry,
308 const ElementVolumeVariables<i>& elemVolVars,
309 const SubControlVolume<i>& scv) const
310 {
311 const auto& solidSol = this->curSol(solidDomainIdx);
312 const auto& voidSol = this->curSol(voidDomainIdx);
313
314 Scalar source = 0.0;
315 const auto& connections = [&]
316 {
317 if constexpr(domainI == solidDomainIdx)
318 return couplingMapper().solidToVoidConnections(scv.dofIndex());
319 else //voidDomainIdx
320 return couplingMapper().voidToSolidConnections(scv.dofIndex());
321 }();
322
323 // iterate over all connection throats
324 for (const auto& connection : connections)
325 {
326 const Scalar t = getConnectionTransmissiblity(domainI, connection, elemVolVars, scv);
327 const Scalar deltaT = [&]
328 {
329 if constexpr(domainI == solidDomainIdx)
330 return solidSol[scv.dofIndex()][Indices<solidDomainIdx>::temperatureIdx] - voidSol[connection.voidVertexIdx][Indices<voidDomainIdx>::temperatureIdx];
331 else //voidDomainIdx
332 return voidSol[scv.dofIndex()][Indices<voidDomainIdx>::temperatureIdx] - solidSol[connection.solidVertexIdx][Indices<solidDomainIdx>::temperatureIdx];
333 }();
334
335 source -= t * deltaT;
336 }
337
338 source /= (scv.volume() * fvGeometry.gridGeometry().coordinationNumber()[scv.dofIndex()]);
339 return source;
340 }
341
342 template<class Connection, class Context>
343 Scalar convectiveHeatFluxForOneConnection(const Connection& connection, const Context& context) const
344 {
345 const auto& solidSol = this->curSol(solidDomainIdx);
346 const auto& voidSol = this->curSol(voidDomainIdx);
347 const Scalar tSolid = solidSol[connection.solidVertexIdx];
348 Scalar resultConvection = 0.0;
349
350 // iterate over all convection void elements
351 for (const auto& [localConvectionVoidElementIdx, convectionVoidElementIdx] : enumerate(connection.convectionVoidElementIdx))
352 {
353 const auto& voidElement = voidGridGeometry_->element(convectionVoidElementIdx);
354 const auto& voidFVGeometry = context.voidFVGeometry[localConvectionVoidElementIdx];
355 const auto& voidElemVolVars = context.voidElemVolVars[localConvectionVoidElementIdx];
356 const auto& voidElemFluxVarsCache = context.voidElemFluxVarsCache[localConvectionVoidElementIdx];
357
358 const Scalar distance = [&, convectionVoidElementIdx = convectionVoidElementIdx, solidVertexIdx = connection.solidVertexIdx]
359 {
360 const auto& throatCenter = this->problem(voidDomainIdx).spatialParams().throatCenter(convectionVoidElementIdx);
361 for (const auto& solidScv : scvs(context.solidFVGeometry[0]))
362 {
363 if (solidScv.dofIndex() == solidVertexIdx)
364 return (solidScv.dofPosition() - throatCenter).two_norm();
365 }
366 DUNE_THROW(Dune::InvalidStateException, "No solid scv found");
367 }();
368
369 using VoidFluxVariables = GetPropType<SubDomainTypeTag<voidDomainIdx>, Properties::FluxVariables>;
370 VoidFluxVariables fluxVars;
371 const auto& scvf = voidFVGeometry.scvf(0/*localScvfIdx*/); //only one scvf per element -> localScvfIdx = 0
372 fluxVars.init(this->problem(voidDomainIdx), voidElement, voidFVGeometry, voidElemVolVars, scvf, voidElemFluxVarsCache);
373
374 static constexpr auto phaseIdx = 0;
375 const Scalar flux = fluxVars.advectiveFlux(phaseIdx, [phaseIdx = phaseIdx](const auto& volVars){ return volVars.mobility(phaseIdx);});
376 const Scalar velocity = flux / voidElemFluxVarsCache[scvf].throatCrossSectionalArea(phaseIdx);
377
378 const auto tFluidMean = [&]
379 {
380 Scalar result = 0.0;
381 const auto numScv = voidFVGeometry.numScv();
382 assert(numScv == 2);
383 for (const auto& voidScv : scvs(voidFVGeometry))
384 result += 1.0/numScv * voidSol[voidScv.dofIndex()][Indices<voidDomainIdx>::temperatureIdx];
385 return result;
386 };
387
388 const auto tFluidUpstream = [&]
389 {
390 const auto upstreamDofIdx = flux > 0.0 ? voidFVGeometry.scv(scvf.insideScvIdx()).dofIndex() : voidFVGeometry.scv(scvf.outsideScvIdx()).dofIndex();
391 return voidSol[upstreamDofIdx][Indices<voidDomainIdx>::temperatureIdx];
392 };
393
394 enum class FluidTemperatureMode {mean, self, upstream};
395 static const auto fluidTemperatureMode = [&]
396 {
397 static const auto mode = getParam<std::string>("DualNetwork.FluidTemperatureMode", "mean");
398 std::cout << "Using FluidTemperatureMode " << mode << std::endl;
399 if (mode == "mean")
400 return FluidTemperatureMode::mean;
401 else if (mode == "self")
402 return FluidTemperatureMode::self;
403 else if (mode == "upstream")
404 return FluidTemperatureMode::upstream;
405 else
406 DUNE_THROW(Dune::IOError, mode << " is not a valid FluidTemperatureMode");
407 }();
408
409 const Scalar tFluid = [&, voidVertexIdx = connection.voidVertexIdx]
410 {
411 if (fluidTemperatureMode == FluidTemperatureMode::mean)
412 return tFluidMean();
413 else if (fluidTemperatureMode == FluidTemperatureMode::self)
414 return voidSol[voidVertexIdx][Indices<voidDomainIdx>::temperatureIdx];
415 else
416 return tFluidUpstream();
417 }();
418
419 const Scalar meanKinematicViscosity = 0.5*(voidElemVolVars[0].viscosity(phaseIdx)/voidElemVolVars[0].density(phaseIdx)
420 + voidElemVolVars[1].viscosity(phaseIdx)/voidElemVolVars[1].density(phaseIdx));
421 const Scalar characteristicLength = 2.0*voidElemFluxVarsCache[scvf].throatInscribedRadius();
422 using std::abs;
423 const Scalar Re = DimLessNum::reynoldsNumber(abs(velocity), characteristicLength, meanKinematicViscosity);
424
425 static const Scalar fixedLambda = getParam<Scalar>("DualNetwork.FixedConvectionLambda", -1.0);
426 static const Scalar lambaFactor = getParam<Scalar>("DualNetwork.ConvectionLambaFactor", 0.9);
427 static const Scalar lambaExponent = getParam<Scalar>("DualNetwork.ConvectionLambaExponent", 0.4);
428 using std::pow;
429 const Scalar lambda = fixedLambda > 0.0 ? fixedLambda : 1.0 + lambaFactor*pow(Re, lambaExponent); //approximation: see eq.30 in Koch et al (2021) https://doi.org/10.1007/s11242-021-01602-5
430 const Scalar selfA = connection.connectionArea / connection.convectionVoidElementIdx.size();
431
432 const auto neighborA = [&]
433 {
434 // get the area associated to the other void dof
435 for (const auto& voidScv : scvs(voidFVGeometry))
436 {
437 if (voidScv.dofIndex() != connection.voidVertexIdx)
438 {
439 const auto& otherConnections = couplingMapper().voidToSolidConnections(voidScv.dofIndex());
440 for (const auto& otherConn : otherConnections)
441 {
442 if (otherConn.solidVertexIdx == connection.solidVertexIdx)
443 {
444 if (otherConn.voidVertexIdx != voidScv.dofIndex())
445 DUNE_THROW(Dune::InvalidStateException, "Void dofs don't match");
446
447 return otherConn.connectionArea/otherConn.convectionVoidElementIdx.size();
448 }
449 }
450 }
451 }
452 DUNE_THROW(Dune::InvalidStateException, "No neighbor area found");
453 };
454
455 static const bool useAvgA = getParam<bool>("DualNetwork.UseAverageConvectionArea", false);
456 const Scalar A = useAvgA ? 0.5*(selfA + neighborA()) : selfA;
457
458 const Scalar deltaT = (elementCouplingContext_.boundDomainId() == voidDomainIdx) ? (tSolid - tFluid) : (tFluid - tSolid);
459
460 static const int verbose = getParam<int>("DualNetwork.SourceVerboseForDof", -1);
461 if (verbose >= 0 && (connection.voidVertexIdx == verbose || connection.solidVertexIdx == verbose))
462 {
463 std::cout << "\n" << std::endl;
464 const auto domain = elementCouplingContext_.boundDomainId() == solidDomainIdx ? "solid" : "void";
465 std::cout << "At " << domain << ", dof " << verbose << ", flow elem " << convectionVoidElementIdx << ", globalId " << connection.id << std::endl;
466 std::cout << std::scientific << std::setprecision(15) << "velocity " << velocity << ", Re " << Re << ", delTaT " << deltaT << ", result " << lambda*A/distance*deltaT << std::endl;
467 std::cout << std::scientific << std::setprecision(15) << "A " << A << ", distance " << distance << std::endl;
468 std::cout << std::endl;
469 }
470
471 resultConvection += lambda*A/distance * deltaT;
472 }
473
474 return resultConvection;
475 }
476
481 template<std::size_t i>
482 Scalar convectionSource(Dune::index_constant<i> domainI,
483 const Element<i>& element,
484 const FVElementGeometry<i>& fvGeometry,
485 const ElementVolumeVariables<i>& elemVolVars,
486 const SubControlVolume<i>& scv) const
487 {
488 bindCouplingContext(domainI, element);
489
490 static const int verbose = getParam<int>("DualNetwork.SourceVerboseForDof", -1);
491 if (scv.dofIndex() == verbose)
492 std::cout << "Start Source at elemn " << fvGeometry.gridGeometry().elementMapper().index(element) << " *******************************" << std::endl;
493
494 // iterate over all connection throats
495 const auto& connections = [&]
496 {
497 if constexpr (domainI == solidDomainIdx)
498 return couplingMapper().solidToVoidConnections(scv.dofIndex());
499 else
500 return couplingMapper().voidToSolidConnections(scv.dofIndex());
501 }();
502
503 Scalar source = 0.0;
504 const auto& contextForPore = elementCouplingContext_[scv.dofIndex()];
505
506 for (const auto& [localConnectionIdx, connection] : enumerate(connections))
507 source += convectiveHeatFluxForOneConnection(connection, contextForPore[localConnectionIdx]);
508
509 if (scv.dofIndex() == verbose)
510 std::cout << std::scientific << std::setprecision(15) << "total conv source " << source << "\n\n ********************" << std::endl;
511
512 source /= (scv.volume() * fvGeometry.gridGeometry().coordinationNumber()[scv.dofIndex()]);
513
514 return source;
515 }
516
517 //TODO: this should not be in the general coupling manager
518 template<std::size_t i, std::size_t j>
519 Scalar sourceWithFixedTransmissibility(Dune::index_constant<i> domainI,
520 const Element<i>& element,
521 const FVElementGeometry<i>& fvGeometry,
522 const ElementVolumeVariables<i>& elemVolVars,
523 const SubControlVolume<i>& scv,
524 Dune::index_constant<j> domainJ) const
525 {
526 const auto& voidSol = this->curSol(voidDomainIdx);
527 const auto& solidSol = this->curSol(solidDomainIdx);
528
529 Scalar source = 0.0;
530
531 // iterate over all connection throats
532 for (const auto& connection : couplingMapper().voidToSolidConnections(scv.dofIndex()))
533 {
534 const Scalar t = this->problem(voidDomainIdx).getInternalReferenceHeatTransmissibilityCoupling();
535 const Scalar deltaT = [&]
536 {
537 if constexpr(domainI == solidDomainIdx)
538 return solidSol[scv.dofIndex()][Indices<solidDomainIdx>::temperatureIdx] - voidSol[connection.voidVertexIdx][Indices<voidDomainIdx>::temperatureIdx];
539 else //voidDomainIdx
540 return voidSol[scv.dofIndex()][Indices<voidDomainIdx>::temperatureIdx] - solidSol[connection.solidVertexIdx][Indices<solidDomainIdx>::temperatureIdx];
541 }();
542
543 source -= t * deltaT;
544 }
545
546 source /= (scv.volume() * fvGeometry.gridGeometry().coordinationNumber()[scv.dofIndex()]);
547 return source;
548 }
549
550 template<std::size_t i, class Connection>
551 Scalar getConnectionTransmissiblity(Dune::index_constant<i> domainI,
552 const Connection& connection,
553 const ElementVolumeVariables<i>& elemVolVars,
554 const SubControlVolume<i>& scv) const
555 {
556 static constexpr bool isVoid = (domainI == voidDomainIdx);
557
558 const auto poreRadiusVoid = [&]
559 {
560 static const bool useExactPoreRadiusVoid = getParam<bool>("DualNetwork.UseExactPoreRadiusVoid", false);
561 if (useExactPoreRadiusVoid)
562 {
563 using std::sqrt;
564 static const Scalar R = getParam<Scalar>("DualNetwork.SphereRadius", 50e-6);
565 static const Scalar overlapFactor = getParam<Scalar>("DualNetwork.OverlapFactor");
566 static const Scalar dx = overlapFactor*R;
567 static const Scalar r = sqrt(3.0) * dx - R;
568 return r;
569 }
570 else
571 return gridGeometry(voidDomainIdx).poreInscribedRadius(connection.voidVertexIdx);
572 }();
573
574 const auto poreRadiusSolid = [&]
575 {
576 static const bool useExactPoreRadiusSolid = getParam<bool>("DualNetwork.UseExactPoreRadiusSolid", false);
577 if (useExactPoreRadiusSolid)
578 {
579 static const Scalar R = getParam<Scalar>("DualNetwork.SphereRadius", 50e-6);
580 return R;
581 }
582 else
583 return this->problem(solidDomainIdx).spatialParams().poreExtendedRadius(connection.solidVertexIdx);
584 }();
585
586 const Scalar fluidThermalConductivity = [&]
587 {
588 if constexpr (isVoid)
589 return elemVolVars[scv].effectiveThermalConductivity();
590 else
591 {
592 const auto& voidElement = voidGridGeometry_->element(connection.someVoidElementIdx);
593 auto voidFVGeometry = localView(*voidGridGeometry_);
594 voidFVGeometry.bindElement(voidElement);
595
596 for (const auto& voidScv : scvs(voidFVGeometry))
597 {
598 if (voidScv.dofIndex() == connection.voidVertexIdx)
599 return volVars(voidDomainIdx, voidElement, voidScv).effectiveThermalConductivity();
600 }
601
602 DUNE_THROW(Dune::InvalidStateException, "No scv found");
603 }
604 }();
605
606 const Scalar solidThermalConductivity = [&]
607 {
608 if constexpr (!isVoid) //solid
609 return elemVolVars[scv].effectiveThermalConductivity();
610 else
611 {
612 const auto& solidElement = solidGridGeometry_->element(connection.someSolidElementIdx);
613 auto solidFVGeometry = localView(*solidGridGeometry_);
614 solidFVGeometry.bindElement(solidElement);
615
616 for (const auto& solidScv : scvs(solidFVGeometry))
617 {
618 if (solidScv.dofIndex() == connection.solidVertexIdx)
619 return volVars(solidDomainIdx, solidElement, solidScv).effectiveThermalConductivity();
620 }
621
622 DUNE_THROW(Dune::InvalidStateException, "No scv found");
623 }
624 }();
625
626 const Scalar kappa = fluidThermalConductivity / solidThermalConductivity;
627 static const Scalar Nu = getParam<Scalar>("DualNetwork.Nu", 1.0);
628 static const Scalar Bi = getParam<Scalar>("DualNetwork.Bi", 1.0);
629
630 static const bool useExactConnectionLength = getParam<bool>("DualNetwork.UseExactConnectionLength", false);
631 const Scalar length = useExactConnectionLength ? poreRadiusSolid + poreRadiusVoid : connection.connectionLength;
632
633 static const bool useExactConnectionAreaSphere = getParam<bool>("DualNetwork.UseExactConnectionAreaSphere", false);
634 static const Scalar connectionAreaShapeFactor = getParam<Scalar>("DualNetwork.ConnectionAreaShapeFactor", 0.9);
635 const Scalar area = [&]()
636 {
637 if (useExactConnectionAreaSphere)
638 {
639 static const Scalar R = getParam<Scalar>("DualNetwork.SphereRadius", 50e-6);
640 static const Scalar overlapFactor = getParam<Scalar>("DualNetwork.OverlapFactor");
641 static const auto dx = overlapFactor*R;
642 static const auto h = R - dx;
643 static const auto interfacialArea = 4*M_PI*R*R - 6*(2*M_PI*R*h);
644 assert(std::abs(length - std::sqrt(3.0) * dx) < 1e-14); // TODO remove
645 return interfacialArea/8.0*connectionAreaShapeFactor;
646 }
647 else
648 return connection.connectionArea*connectionAreaShapeFactor;
649 }();
650 //distance weighted harmonic mean of thermal conductivities
651 const Scalar meanThermalConductivity = (fluidThermalConductivity*Bi*(poreRadiusSolid + poreRadiusVoid))/(poreRadiusSolid*kappa + poreRadiusVoid*Bi/Nu);
652 return area / length * meanThermalConductivity;
653 }
654
655 // \}
656
660 template<std::size_t i>
661 VolumeVariables<i> volVars(Dune::index_constant<i> domainI,
662 const Element<i>& element,
663 const SubControlVolume<i>& scv) const
664 {
665 VolumeVariables<i> volVars;
666 const auto elemSol = elementSolution(element, this->curSol(domainI), gridGeometry(domainI));
667 volVars.update(elemSol, this->problem(domainI), element, scv);
668 return volVars;
669 }
670
671 template<std::size_t i, std::size_t j, class LocalAssemblerI>
672 decltype(auto) evalCouplingResidual(Dune::index_constant<i> domainI,
673 const LocalAssemblerI& localAssemblerI,
674 Dune::index_constant<j> domainJ,
675 std::size_t dofIdxGlobalJ)
676 {
677 static_assert(i != j, "A domain cannot be coupled to itself!");
678
679 typename LocalAssemblerI::LocalResidual::ElementResidualVector residual;
680
681 const auto& element = localAssemblerI.element();
682 const auto& fvGeometry = localAssemblerI.fvGeometry();
683 const auto& curElemVolVars = localAssemblerI.curElemVolVars();
684
685 residual.resize(fvGeometry.numScv());
686 for (const auto& scv : scvs(fvGeometry))
687 {
688 auto couplingSource = this->problem(domainI).source(element, fvGeometry, curElemVolVars, scv);
689 couplingSource *= -scv.volume()*curElemVolVars[scv].extrusionFactor();
690 residual[scv.indexInElement()] = couplingSource;
691 }
692
693 return residual;
694 }
695
697 template<std::size_t i, class Assembler = int>
698 void bindCouplingContext(Dune::index_constant<i> domainI, const Element<i>& element, const Assembler& assembler = 0) const
699 { elementCouplingContext_.bind(domainI, element, *this); }
700
704 template<std::size_t i, class LocalAssemblerI, std::size_t j, class PriVars>
705 void updateCouplingContext(Dune::index_constant<i> domainI,
706 const LocalAssemblerI& localAssemblerI,
707 Dune::index_constant<j> domainJ,
708 const std::size_t dofIdxGlobalJ,
709 const PriVars& priVars,
710 int pvIdxJ)
711 {
712 this->curSol(domainJ)[dofIdxGlobalJ][pvIdxJ] = priVars[pvIdxJ];
713
714 // each element has two pores for which we need to bind some connection coupling context
715 for (auto& context : elementCouplingContext_.data())
716 {
717 for (auto& connInfo : context.second)
718 {
719 const auto& staticConnectionInfo = couplingMapper().connectionInfo()[connInfo.connectionGlobalId];
720
721 // when the solid dof is deflected, just updated the solid volVars
722 if constexpr (domainJ == solidDomainIdx)
723 {
724 const auto& solidElement = gridGeometry(domainJ).element(staticConnectionInfo.someSolidElementIdx);
725 for (const auto& scv : scvs(connInfo.solidFVGeometry.front()))
726 {
727 solidElementSolution_[scv.localDofIndex()] = this->curSol(domainJ)[scv.dofIndex()];
728 if (scv.dofIndex() == dofIdxGlobalJ)
729 connInfo.solidVolVars.update(solidElementSolution_, this->problem(domainJ), solidElement, scv);
730 }
731 }
732 else // deflection of void dofs
733 {
734 assert(staticConnectionInfo.convectionVoidElementIdx.size() == connInfo.voidFVGeometry.size());
735 for (int voidElemLocalIdx = 0; voidElemLocalIdx < staticConnectionInfo.convectionVoidElementIdx.size(); ++voidElemLocalIdx)
736 {
737 const auto eIdx = staticConnectionInfo.convectionVoidElementIdx[voidElemLocalIdx];
738 const auto& element = gridGeometry(voidDomainIdx).element(eIdx);
739 const auto& fvGeometry = connInfo.voidFVGeometry[voidElemLocalIdx];
740 auto& elemVolVars = connInfo.voidElemVolVars[voidElemLocalIdx];
741
742 for (const auto& scv : scvs(fvGeometry))
743 {
744 if (scv.dofIndex() == dofIdxGlobalJ)
745 {
746 voidElementSolution_[scv.localDofIndex()] = this->curSol(voidDomainIdx)[scv.dofIndex()];
747 getVolVarAccess_(domainJ, gridVars_(voidDomainIdx).curGridVolVars(), elemVolVars, scv).update(voidElementSolution_, this->problem(voidDomainIdx), element, scv);
748 }
749 }
750
751 for (const auto& scvf : scvfs(fvGeometry))
752 {
753 if constexpr (getPropValue<SubDomainTypeTag<j>, Properties::EnableGridFluxVariablesCache>())
754 gridVars_(voidDomainIdx).gridFluxVarsCache().cache(eIdx, scvf.index()).update(problem(voidDomainIdx), element, fvGeometry, elemVolVars, scvf);
755 else
756 connInfo.voidElemFluxVarsCache[voidElemLocalIdx][scvf].update(this->problem(voidDomainIdx), element, fvGeometry, elemVolVars, scvf);
757 }
758 }
759 }
760 }
761 }
762 }
763
764 const auto& couplingContext() const
765 { return elementCouplingContext_; }
766
767
768 template<std::size_t i>
769 const auto& gridGeometry(Dune::index_constant<i> domainI) const
770 {
771 if constexpr (i == voidDomainIdx)
772 return *voidGridGeometry_;
773 else
774 return *solidGridGeometry_;
775 }
776
778 { return *couplingMapper_; }
779
784 void setGridVariables(GridVariablesTuple&& gridVariables)
786
792 template<class GridVariables, std::size_t i>
793 void setGridVariables(std::shared_ptr<GridVariables> gridVariables, Dune::index_constant<i> domainIdx)
794 { std::get<i>(gridVariables_) = gridVariables; }
795
800 template<std::size_t i>
801 const GridVariables<i>& gridVariables(Dune::index_constant<i> domainIdx) const
802 {
803 if (std::get<i>(gridVariables_))
804 return *std::get<i>(gridVariables_);
805 else
806 DUNE_THROW(Dune::InvalidStateException, "The gridVariables pointer was not set. Use setGridVariables() before calling this function");
807 }
808
815 template<std::size_t id, class JacobianPattern>
816 void extendJacobianPattern(Dune::index_constant<id> domainI, JacobianPattern& pattern) const
817 {
818 extendedSourceStencil_.extendJacobianPattern(*this, domainI, pattern);
819 }
820
828 template<std::size_t i, class LocalAssemblerI, class JacobianMatrixDiagBlock, class GridVariables>
829 void evalAdditionalDomainDerivatives(Dune::index_constant<i> domainI,
830 const LocalAssemblerI& localAssemblerI,
831 const typename LocalAssemblerI::LocalResidual::ElementResidualVector&,
832 JacobianMatrixDiagBlock& A,
833 GridVariables& gridVariables)
834 {
835 // std::cout << "calling evalAdditionalDomainDerivatives " << std::endl;
836 extendedSourceStencil_.evalAdditionalDomainDerivatives(*this, domainI, localAssemblerI, this->curSol(domainI), A, gridVariables); //TODO: call without curSol, but currently protected .../dumux/dumux/multidomain/couplingmanager.hh
837 }
838
840 std::vector<std::size_t>& emptyStencil()
841 { return emptyStencil_; }
842
843
845 template<std::size_t i>
846 const std::vector<std::size_t>& emptyStencil(Dune::index_constant<i> domainI) const
847 { return emptyStencil_; }
848
849 template<std::size_t i>
850 const auto& gridView(Dune::index_constant<i> domainI) const
851 {
852 return gridGeometry(domainI).gridView();
853 }
854
855
857 {
859
860 for (const auto& element : elements(gridView(voidDomainIdx)))
861 {
862 const auto eIdx = gridGeometry(voidDomainIdx).elementMapper().index(element);
863 const auto vIdx0 = gridGeometry(voidDomainIdx).vertexMapper().subIndex(element, 0, 1);
864 const auto vIdx1 = gridGeometry(voidDomainIdx).vertexMapper().subIndex(element, 1, 1);
865
866 for (const auto& is : intersections(gridView(voidDomainIdx), element))
867 {
868 if (is.neighbor())
869 {
870 const auto& outsideElement = is.outside();
871 for (int i = 0; i < 2; ++i)
872 {
873 const auto outsideVertexIdx = gridGeometry(voidDomainIdx).vertexMapper().subIndex(outsideElement, i, 1);
874 if (outsideVertexIdx != vIdx0 && outsideVertexIdx != vIdx1)
875 extendedSourceStencil_.stencil()[eIdx].push_back(outsideVertexIdx);
876 }
877 }
878 }
879
881 }
882 }
883
884
885protected:
886
887 template<std::size_t i>
888 VolumeVariables<i>& getVolVarAccess_(Dune::index_constant<i> domainIdx, GridVolumeVariables<i>& gridVolVars, ElementVolumeVariables<i>& elemVolVars, const SubControlVolume<i>& scv)
889 {
890 if constexpr (getPropValue<SubDomainTypeTag<i>, Properties::EnableGridVolumeVariablesCache>())
891 return gridVolVars.volVars(scv);
892 else
893 return elemVolVars[scv];
894 }
895
900 template<std::size_t i>
901 GridVariables<i>& gridVars_(Dune::index_constant<i> domainIdx)
902 {
903 if (std::get<i>(gridVariables_))
904 return *std::get<i>(gridVariables_);
905 else
906 DUNE_THROW(Dune::InvalidStateException, "The gridVariables pointer was not set. Use setGridVariables() before calling this function");
907 }
908
910 void removeDuplicates_(std::vector<std::size_t>& stencil)
911 {
912 std::sort(stencil.begin(), stencil.end());
913 stencil.erase(std::unique(stencil.begin(), stencil.end()), stencil.end());
914 }
915
916
918
919 std::vector<std::size_t> emptyStencil_;
920 std::unique_ptr<const CouplingMapper> couplingMapper_;
921 const GridGeometry<voidDomainIdx>* voidGridGeometry_;
922 const GridGeometry<solidDomainIdx>* solidGridGeometry_;
923
924 VoidElementSolution voidElementSolution_;
925 SolidElementSolution solidElementSolution_;
926 mutable ElementCouplingContext elementCouplingContext_;
927
931 GridVariablesTuple gridVariables_;
932
935};
936
937}; // end namespace Dumux::PoreNetwork
938
939#endif
The interface of the coupling manager for multi domain problems.
Definition multidomain/couplingmanager.hh:48
void setSubProblems(const std::tuple< std::shared_ptr< SubProblems >... > &problems)
set the pointers to the sub problems
Definition multidomain/couplingmanager.hh:286
const Problem< i > & problem(Dune::index_constant< i > domainIdx) const
Return a reference to the sub problem.
Definition multidomain/couplingmanager.hh:308
SubSolutionVector< i > & curSol(Dune::index_constant< i > domainIdx)
the solution vector of the subproblem
Definition multidomain/couplingmanager.hh:337
void updateSolution(const SolutionVector &curSol)
Updates the entire solution vector, e.g. before assembly or after grid adaption Overload might want t...
Definition multidomain/couplingmanager.hh:218
Collection of functions which calculate dimensionless numbers. Each number has it's own function....
Definition dimensionlessnumbers.hh:53
static Scalar reynoldsNumber(const Scalar darcyMagVelocity, const Scalar charcteristicLength, const Scalar kinematicViscosity)
Calculate the Reynolds Number [-] (Re).
Definition dimensionlessnumbers.hh:76
Coupling mapper for Stokes and Darcy domains with equal dimension.
Definition dualnetwork/couplingmapper.hh:40
auto voidToSolidConnections(const std::size_t dofIdx) const
Returns an iterator allowing for (const auto& conn : voidToSolidConnections(dofIdx)) {....
Definition dualnetwork/couplingmapper.hh:255
const auto & voidToSolidStencils() const
Definition dualnetwork/couplingmapper.hh:242
const std::vector< bool > & isCoupledVoidDof() const
Definition dualnetwork/couplingmapper.hh:248
const std::vector< bool > & isCoupledSolidDof() const
Definition dualnetwork/couplingmapper.hh:251
const auto & connectionInfo() const
Definition dualnetwork/couplingmapper.hh:277
auto solidToVoidConnections(const std::size_t dofIdx) const
Definition dualnetwork/couplingmapper.hh:263
const auto & solidToVoidStencils() const
Definition dualnetwork/couplingmapper.hh:245
A class managing an extended source stencil.
Definition dualnetwork/extendedsourcestencil.hh:36
Coupling manager for dual network approach for pore network models.
Definition multidomain/dualnetwork/couplingmanager.hh:48
static constexpr auto solidDomainIdx
Definition multidomain/dualnetwork/couplingmanager.hh:85
void setGridVariables(GridVariablesTuple &&gridVariables)
set the pointers to the grid variables
Definition multidomain/dualnetwork/couplingmanager.hh:784
void evalAdditionalDomainDerivatives(Dune::index_constant< i > domainI, const LocalAssemblerI &localAssemblerI, const typename LocalAssemblerI::LocalResidual::ElementResidualVector &, JacobianMatrixDiagBlock &A, GridVariables &gridVariables)
evaluate additional derivatives of the element residual of a domain with respect to dofs in the same ...
Definition multidomain/dualnetwork/couplingmanager.hh:829
const auto & gridView(Dune::index_constant< i > domainI) const
Definition multidomain/dualnetwork/couplingmanager.hh:850
bool convectiveHeatTransfer_
Definition multidomain/dualnetwork/couplingmanager.hh:917
const CouplingStencil & couplingStencil(Dune::index_constant< i > domainI, const Element< i > &element, Dune::index_constant< j > domainJ) const
Methods to be accessed by the assembly.
Definition multidomain/dualnetwork/couplingmanager.hh:269
std::vector< std::size_t > & emptyStencil()
Return a reference to an empty stencil.
Definition multidomain/dualnetwork/couplingmanager.hh:840
VolumeVariables< i > volVars(Dune::index_constant< i > domainI, const Element< i > &element, const SubControlVolume< i > &scv) const
Return the volume variables of domain i for a given element and scv.
Definition multidomain/dualnetwork/couplingmanager.hh:661
std::unique_ptr< const CouplingMapper > couplingMapper_
Definition multidomain/dualnetwork/couplingmanager.hh:920
void setGridVariables(std::shared_ptr< GridVariables > gridVariables, Dune::index_constant< i > domainIdx)
set a pointer to one of the grid variables
Definition multidomain/dualnetwork/couplingmanager.hh:793
const auto & couplingContext() const
Definition multidomain/dualnetwork/couplingmanager.hh:764
void init(std::shared_ptr< Problem< solidDomainIdx > > solidProblem, std::shared_ptr< Problem< voidDomainIdx > > voidProblem, const HostGridView &hostGridView, const HostGridData &hostGridData, const VoidGridView &voidGridView, const SolidGridView &solidGridView, const SolutionVector &curSol)
Methods to be accessed by main.
Definition multidomain/dualnetwork/couplingmanager.hh:232
const auto & gridGeometry(Dune::index_constant< i > domainI) const
Definition multidomain/dualnetwork/couplingmanager.hh:769
Scalar convectiveHeatFluxForOneConnection(const Connection &connection, const Context &context) const
Definition multidomain/dualnetwork/couplingmanager.hh:343
const GridGeometry< voidDomainIdx > * voidGridGeometry_
Definition multidomain/dualnetwork/couplingmanager.hh:921
SolidElementSolution solidElementSolution_
Definition multidomain/dualnetwork/couplingmanager.hh:925
const std::vector< std::size_t > & emptyStencil(Dune::index_constant< i > domainI) const
Return a reference to an empty stencil.
Definition multidomain/dualnetwork/couplingmanager.hh:846
VoidElementSolution voidElementSolution_
Definition multidomain/dualnetwork/couplingmanager.hh:924
void setupExtendedStencil()
Definition multidomain/dualnetwork/couplingmanager.hh:856
PoreNetwork::PNMHeatExtendedSourceStencil< ThisType > extendedSourceStencil_
the extended source stencil object
Definition multidomain/dualnetwork/couplingmanager.hh:934
const CouplingMapper & couplingMapper() const
Definition multidomain/dualnetwork/couplingmanager.hh:777
bool isCoupledPore(Dune::index_constant< i > domainI, const std::size_t dofIdx) const
Returns whether a given solid grain/void pore body is coupled to the other domain.
Definition multidomain/dualnetwork/couplingmanager.hh:289
Scalar conductionSource(Dune::index_constant< i > domainI, const Element< i > &element, const FVElementGeometry< i > &fvGeometry, const ElementVolumeVariables< i > &elemVolVars, const SubControlVolume< i > &scv) const
Returns summed conductive flux between void and solid for one void pore body or one solid grain.
Definition multidomain/dualnetwork/couplingmanager.hh:305
std::vector< std::size_t > emptyStencil_
Definition multidomain/dualnetwork/couplingmanager.hh:919
void removeDuplicates_(std::vector< std::size_t > &stencil)
Removes duplicate entries from the coupling stencils.
Definition multidomain/dualnetwork/couplingmanager.hh:910
GridVariablesTuple gridVariables_
A tuple of std::shared_ptrs to the grid variables of the sub problems.
Definition multidomain/dualnetwork/couplingmanager.hh:931
ElementCouplingContext elementCouplingContext_
Definition multidomain/dualnetwork/couplingmanager.hh:926
Scalar convectionSource(Dune::index_constant< i > domainI, const Element< i > &element, const FVElementGeometry< i > &fvGeometry, const ElementVolumeVariables< i > &elemVolVars, const SubControlVolume< i > &scv) const
Returns summed conductive heat fluxes for one void pore body coupled to solid grains (or the other wa...
Definition multidomain/dualnetwork/couplingmanager.hh:482
GridVariables< i > & gridVars_(Dune::index_constant< i > domainIdx)
Return a reference to the grid variables of a sub problem.
Definition multidomain/dualnetwork/couplingmanager.hh:901
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 multidomain/dualnetwork/couplingmanager.hh:816
void bindCouplingContext(Dune::index_constant< i > domainI, const Element< i > &element, const Assembler &assembler=0) const
Bind the coupling context for a low dim element TODO remove Assembler.
Definition multidomain/dualnetwork/couplingmanager.hh:698
decltype(auto) evalCouplingResidual(Dune::index_constant< i > domainI, const LocalAssemblerI &localAssemblerI, Dune::index_constant< j > domainJ, std::size_t dofIdxGlobalJ)
Definition multidomain/dualnetwork/couplingmanager.hh:672
static constexpr auto voidDomainIdx
Definition multidomain/dualnetwork/couplingmanager.hh:86
const GridVariables< i > & gridVariables(Dune::index_constant< i > domainIdx) const
Return a reference to the grid variables of a sub problem.
Definition multidomain/dualnetwork/couplingmanager.hh:801
std::unordered_map< std::size_t, CouplingStencil > CouplingStencils
export stencil types
Definition multidomain/dualnetwork/couplingmanager.hh:224
VolumeVariables< i > & getVolVarAccess_(Dune::index_constant< i > domainIdx, GridVolumeVariables< i > &gridVolVars, ElementVolumeVariables< i > &elemVolVars, const SubControlVolume< i > &scv)
Definition multidomain/dualnetwork/couplingmanager.hh:888
const GridGeometry< solidDomainIdx > * solidGridGeometry_
Definition multidomain/dualnetwork/couplingmanager.hh:922
MDTraits MultiDomainTraits
export traits
Definition multidomain/dualnetwork/couplingmanager.hh:222
void updateCouplingContext(Dune::index_constant< i > domainI, const LocalAssemblerI &localAssemblerI, Dune::index_constant< j > domainJ, const std::size_t dofIdxGlobalJ, const PriVars &priVars, int pvIdxJ)
Update the coupling context.
Definition multidomain/dualnetwork/couplingmanager.hh:705
Scalar getConnectionTransmissiblity(Dune::index_constant< i > domainI, const Connection &connection, const ElementVolumeVariables< i > &elemVolVars, const SubControlVolume< i > &scv) const
Definition multidomain/dualnetwork/couplingmanager.hh:551
Scalar sourceWithFixedTransmissibility(Dune::index_constant< i > domainI, const Element< i > &element, const FVElementGeometry< i > &fvGeometry, const ElementVolumeVariables< i > &elemVolVars, const SubControlVolume< i > &scv, Dune::index_constant< j > domainJ) const
Definition multidomain/dualnetwork/couplingmanager.hh:519
Defines all properties used in Dumux.
Collection of functions, calculating dimensionless numbers.
Coupling mapper for Stokes and Darcy domains with equal dimension.
Extended source stencil helper class for coupling managers.
Element solution classes and factory functions.
A Python-like enumerate function.
typename NumEqVectorTraits< PrimaryVariables >::type NumEqVector
A vector with the same size as numbers of equations This is the default implementation and has to be ...
Definition numeqvector.hh:34
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
static ctype distance(const Dune::FieldVector< ctype, dimWorld > &a, const Dune::FieldVector< ctype, dimWorld > &b)
Compute the shortest distance between two points.
Definition distance.hh:282
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition propertysystem.hh:296
Define some often used mathematical functions.
The available discretization methods in Dumux.
The interface of the coupling manager for multi domain problems.
Definition discretization/porenetwork/fvelementgeometry.hh:24
constexpr auto enumerate(Range &&iterable)
A Python-like enumerate function.
Definition enumerate.hh:30
A helper to deduce a vector with the same size as numbers of equations.