3.4
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
Loading...
Searching...
No Matches
subdomainstaggeredlocalassembler.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 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
26#ifndef DUMUX_MULTIDOMAIN_STAGGERED_LOCAL_ASSEMBLER_HH
27#define DUMUX_MULTIDOMAIN_STAGGERED_LOCAL_ASSEMBLER_HH
28
29#include <dune/common/reservedvector.hh>
30#include <dune/common/indices.hh>
31#include <dune/common/hybridutilities.hh>
32#include <dune/grid/common/gridenums.hh> // for GhostEntity
33
42
43namespace Dumux {
44
56template<std::size_t id, class TypeTag, class Assembler, class Implementation, bool isImplicit = true>
57class SubDomainStaggeredLocalAssemblerBase : public FVLocalAssemblerBase<TypeTag, Assembler,Implementation, isImplicit>
58{
60
63 using SolutionVector = typename Assembler::SolutionVector;
64
66 using GridVolumeVariables = typename GridVariables::GridVolumeVariables;
67 using ElementVolumeVariables = typename GridVolumeVariables::LocalView;
68 using Scalar = typename GridVariables::Scalar;
69
70 using ElementFaceVariables = typename GetPropType<TypeTag, Properties::GridFaceVariables>::LocalView;
71 using CellCenterResidualValue = typename LocalResidual::CellCenterResidualValue;
72 using FaceResidualValue = typename LocalResidual::FaceResidualValue;
73
74 using GridGeometry = typename GridVariables::GridGeometry;
75 using FVElementGeometry = typename GridGeometry::LocalView;
76 using SubControlVolumeFace = typename GridGeometry::SubControlVolumeFace;
77 using GridView = typename GridGeometry::GridView;
78 using Element = typename GridView::template Codim<0>::Entity;
79
80 using CouplingManager = typename Assembler::CouplingManager;
81
82 static constexpr auto numEq = GetPropType<TypeTag, Properties::ModelTraits>::numEq();
83
84public:
85 static constexpr auto domainId = typename Dune::index_constant<id>();
86 static constexpr auto cellCenterId = GridGeometry::cellCenterIdx();
87 static constexpr auto faceId = GridGeometry::faceIdx();
88
89 static constexpr auto numEqCellCenter = CellCenterResidualValue::dimension;
90 static constexpr auto faceOffset = numEqCellCenter;
91
92 using ParentType::ParentType;
93
95 const Element& element,
96 const SolutionVector& curSol,
97 CouplingManager& couplingManager)
98 : ParentType(assembler,
99 element,
100 curSol,
101 localView(assembler.gridGeometry(domainId)),
102 localView(assembler.gridVariables(domainId).curGridVolVars()),
103 localView(assembler.gridVariables(domainId).prevGridVolVars()),
104 localView(assembler.gridVariables(domainId).gridFluxVarsCache()),
106 (element.partitionType() == Dune::GhostEntity))
107 , curElemFaceVars_(localView(assembler.gridVariables(domainId).curGridFaceVars()))
108 , prevElemFaceVars_(localView(assembler.gridVariables(domainId).prevGridFaceVars()))
109 , couplingManager_(couplingManager)
110 {}
111
116 template<class JacobianMatrixRow, class SubSol, class GridVariablesTuple>
117 void assembleJacobianAndResidual(JacobianMatrixRow& jacRow, SubSol& res, GridVariablesTuple& gridVariables)
118 {
119 this->asImp_().bindLocalViews();
120 this->elemBcTypes().update(problem(), this->element(), this->fvGeometry());
121
122 assembleJacobianAndResidualImpl_(domainId, jacRow, res, gridVariables);
123 }
124
128 template<class SubSol>
129 void assembleResidual(SubSol& res)
130 {
131 this->asImp_().bindLocalViews();
132 this->elemBcTypes().update(problem(), this->element(), this->fvGeometry());
133
134 if constexpr (domainId == cellCenterId)
135 {
136 const auto cellCenterGlobalI = problem().gridGeometry().elementMapper().index(this->element());
137 res[cellCenterGlobalI] = this->asImp_().assembleCellCenterResidualImpl();
138 }
139 else
140 {
141 for (auto&& scvf : scvfs(this->fvGeometry()))
142 res[scvf.dofIndex()] += this->asImp_().assembleFaceResidualImpl(scvf);
143 }
144 }
145
150 CellCenterResidualValue evalLocalResidualForCellCenter() const
151 {
152 if (!isImplicit)
153 if (this->assembler().isStationaryProblem())
154 DUNE_THROW(Dune::InvalidStateException, "Using explicit jacobian assembler with stationary local residual");
155
156 if (this->elementIsGhost())
157 {
158 return CellCenterResidualValue(0.0);
159 }
160
163 }
164
170 CellCenterResidualValue evalLocalResidualForCellCenter(const ElementVolumeVariables& elemVolVars,
171 const ElementFaceVariables& elemFaceVars) const
172 {
173 auto residual = evalLocalFluxAndSourceResidualForCellCenter(elemVolVars, elemFaceVars);
174
175 if (!this->assembler().isStationaryProblem())
177
178 // handle cells with a fixed Dirichlet value
179 const auto cellCenterGlobalI = problem().gridGeometry().elementMapper().index(this->element());
180 const auto& scvI = this->fvGeometry().scv(cellCenterGlobalI);
181 for (int pvIdx = 0; pvIdx < numEqCellCenter; ++pvIdx)
182 {
183 static constexpr auto offset = numEq - numEqCellCenter;
184 if (this->problem().isDirichletCell(this->element(), this->fvGeometry(), scvI, pvIdx + offset))
185 residual[pvIdx] = this->curSol()[cellCenterId][cellCenterGlobalI][pvIdx] - this->problem().dirichlet(this->element(), scvI)[pvIdx + offset];
186 }
187
188 return residual;
189 }
190
201
209 CellCenterResidualValue evalLocalFluxAndSourceResidualForCellCenter(const ElementVolumeVariables& elemVolVars, const ElementFaceVariables& elemFaceVars) const
210 {
211 return this->localResidual().evalFluxAndSourceForCellCenter(this->element(), this->fvGeometry(), elemVolVars, elemFaceVars, this->elemBcTypes(), this->elemFluxVarsCache());
212 }
213
219 CellCenterResidualValue evalLocalStorageResidualForCellCenter() const
220 {
221 return this->localResidual().evalStorageForCellCenter(this->element(), this->fvGeometry(), this->prevElemVolVars(), this->curElemVolVars());
222 }
223
229 FaceResidualValue evalLocalResidualForFace(const SubControlVolumeFace& scvf) const
230 {
231 if (!isImplicit)
232 if (this->assembler().isStationaryProblem())
233 DUNE_THROW(Dune::InvalidStateException, "Using explicit jacobian assembler with stationary local residual");
234
235 if (this->elementIsGhost())
236 {
237 return FaceResidualValue(0.0);
238 }
239
242 }
243
250 FaceResidualValue evalLocalResidualForFace(const SubControlVolumeFace& scvf,
251 const ElementVolumeVariables& elemVolVars,
252 const ElementFaceVariables& elemFaceVars) const
253 {
254 auto residual = evalLocalFluxAndSourceResidualForFace(scvf, elemVolVars, elemFaceVars);
255
256 if (!this->assembler().isStationaryProblem())
257 residual += evalLocalStorageResidualForFace(scvf);
258
259 this->localResidual().evalDirichletBoundariesForFace(residual, this->problem(), this->element(),
260 this->fvGeometry(), scvf, elemVolVars, elemFaceVars,
261 this->elemBcTypes(), this->elemFluxVarsCache());
262
263 return residual;
264 }
265
272 FaceResidualValue evalLocalFluxAndSourceResidualForFace(const SubControlVolumeFace& scvf) const
273 {
276 }
277
285 FaceResidualValue evalLocalFluxAndSourceResidualForFace(const SubControlVolumeFace& scvf,
286 const ElementVolumeVariables& elemVolVars,
287 const ElementFaceVariables& elemFaceVars) const
288 {
289 return this->localResidual().evalFluxAndSourceForFace(this->element(), this->fvGeometry(), elemVolVars, elemFaceVars, this->elemBcTypes(), this->elemFluxVarsCache(), scvf);
290 }
291
298 FaceResidualValue evalLocalStorageResidualForFace(const SubControlVolumeFace& scvf) const
299 {
300 return this->localResidual().evalStorageForFace(this->element(), this->fvGeometry(), this->prevElemVolVars(), this->curElemVolVars(), this->prevElemFaceVars(), this->curElemFaceVars(), scvf);
301 }
302
303 const Problem& problem() const
304 { return this->assembler().problem(domainId); }
305
307 ElementFaceVariables& curElemFaceVars()
308 { return curElemFaceVars_; }
309
311 ElementFaceVariables& prevElemFaceVars()
312 { return prevElemFaceVars_; }
313
315 const ElementFaceVariables& curElemFaceVars() const
316 { return curElemFaceVars_; }
317
319 const ElementFaceVariables& prevElemFaceVars() const
320 { return prevElemFaceVars_; }
321
322 CouplingManager& couplingManager()
323 { return couplingManager_; }
324
325private:
326
328 template<class JacobianMatrixRow, class SubSol, class GridVariablesTuple>
329 auto assembleJacobianAndResidualImpl_(Dune::index_constant<cellCenterId>, JacobianMatrixRow& jacRow, SubSol& res, GridVariablesTuple& gridVariables)
330 {
331 auto& gridVariablesI = *std::get<domainId>(gridVariables);
332 const auto cellCenterGlobalI = problem().gridGeometry().elementMapper().index(this->element());
333 const auto residual = this->asImp_().assembleCellCenterJacobianAndResidualImpl(jacRow[domainId], gridVariablesI);
334 res[cellCenterGlobalI] = residual;
335
336
337 // for the coupling blocks
338 using namespace Dune::Hybrid;
339 static constexpr auto otherDomainIds = makeIncompleteIntegerSequence<JacobianMatrixRow::size(), domainId>{};
340 forEach(otherDomainIds, [&](auto&& domainJ)
341 {
342 this->asImp_().assembleJacobianCellCenterCoupling(domainJ, jacRow[domainJ], residual, gridVariablesI);
343 });
344
345 // handle cells with a fixed Dirichlet value
346 incorporateDirichletCells_(jacRow);
347 }
348
350 template<class JacobianMatrixRow, class SubSol, class GridVariablesTuple>
351 void assembleJacobianAndResidualImpl_(Dune::index_constant<faceId>, JacobianMatrixRow& jacRow, SubSol& res, GridVariablesTuple& gridVariables)
352 {
353 auto& gridVariablesI = *std::get<domainId>(gridVariables);
354 const auto residual = this->asImp_().assembleFaceJacobianAndResidualImpl(jacRow[domainId], gridVariablesI);
355
356 for(auto&& scvf : scvfs(this->fvGeometry()))
357 res[scvf.dofIndex()] += residual[scvf.localFaceIdx()];
358
359 // for the coupling blocks
360 using namespace Dune::Hybrid;
361 static constexpr auto otherDomainIds = makeIncompleteIntegerSequence<JacobianMatrixRow::size(), domainId>{};
362 forEach(otherDomainIds, [&](auto&& domainJ)
363 {
364 this->asImp_().assembleJacobianFaceCoupling(domainJ, jacRow[domainJ], residual, gridVariablesI);
365 });
366 }
367
369 template<class JacobianMatrixRow>
370 void incorporateDirichletCells_(JacobianMatrixRow& jacRow)
371 {
372 const auto cellCenterGlobalI = problem().gridGeometry().elementMapper().index(this->element());
373
374 // overwrite the partial derivative with zero in case a fixed Dirichlet BC is used
375 static constexpr auto offset = numEq - numEqCellCenter;
376 for (int eqIdx = 0; eqIdx < numEqCellCenter; ++eqIdx)
377 {
378 if (problem().isDirichletCell(this->element(), this->fvGeometry(), this->fvGeometry().scv(cellCenterGlobalI), eqIdx + offset))
379 {
380 using namespace Dune::Hybrid;
381 forEach(integralRange(Dune::Hybrid::size(jacRow)), [&, domainId = domainId](auto&& i)
382 {
383 auto& ccRowI = jacRow[i][cellCenterGlobalI];
384 for (auto col = ccRowI.begin(); col != ccRowI.end(); ++col)
385 {
386 ccRowI[col.index()][eqIdx] = 0.0;
387 // set the diagonal entry to 1.0
388 if ((i == domainId) && (col.index() == cellCenterGlobalI))
389 ccRowI[col.index()][eqIdx][eqIdx] = 1.0;
390 }
391 });
392 }
393 }
394 }
395
396 ElementFaceVariables curElemFaceVars_;
397 ElementFaceVariables prevElemFaceVars_;
398 CouplingManager& couplingManager_;
399};
400
411template<std::size_t id, class TypeTag, class Assembler, class Implementation>
412class SubDomainStaggeredLocalAssemblerImplicitBase : public SubDomainStaggeredLocalAssemblerBase<id, TypeTag, Assembler, Implementation>
413{
415 static constexpr auto domainId = Dune::index_constant<id>();
416public:
417 using ParentType::ParentType;
418
420 {
421 // get some references for convenience
422 auto& couplingManager = this->couplingManager();
423 const auto& element = this->element();
424 const auto& curSol = this->curSol();
425 auto&& fvGeometry = this->fvGeometry();
426 auto&& curElemVolVars = this->curElemVolVars();
427 auto&& curElemFaceVars = this->curElemFaceVars();
428 auto&& elemFluxVarsCache = this->elemFluxVarsCache();
429
430 // bind the caches
431 couplingManager.bindCouplingContext(domainId, element, this->assembler());
432 fvGeometry.bind(element);
436 if (!this->assembler().isStationaryProblem())
437 {
438 this->prevElemVolVars().bindElement(element, fvGeometry, this->assembler().prevSol());
439 this->prevElemFaceVars().bindElement(element, fvGeometry, this->assembler().prevSol());
440 }
441 }
442};
443
455template<std::size_t id, class TypeTag, class Assembler, DiffMethod DM = DiffMethod::numeric, bool implicit = true>
457
478template<std::size_t id, class TypeTag, class Assembler>
479class SubDomainStaggeredLocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, /*implicit=*/true>
480: public SubDomainStaggeredLocalAssemblerImplicitBase<id, TypeTag, Assembler,
481 SubDomainStaggeredLocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, true> >
482{
483 using ThisType = SubDomainStaggeredLocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, /*implicit=*/true>;
487 using CellCenterResidualValue = typename LocalResidual::CellCenterResidualValue;
488 using FaceResidualValue = typename LocalResidual::FaceResidualValue;
489 using Element = typename GetPropType<TypeTag, Properties::GridGeometry>::GridView::template Codim<0>::Entity;
491 using ElementFaceVariables = typename GetPropType<TypeTag, Properties::GridFaceVariables>::LocalView;
492 using FaceVariables = typename ElementFaceVariables::FaceVariables;
494 using FVElementGeometry = typename GridGeometry::LocalView;
495 using SubControlVolumeFace = typename GridGeometry::SubControlVolumeFace;
497 using CellCenterPrimaryVariables = GetPropType<TypeTag, Properties::CellCenterPrimaryVariables>;
500
501 static constexpr bool enableGridFluxVarsCache = getPropValue<TypeTag, Properties::EnableGridFluxVariablesCache>();
502 static constexpr int maxNeighbors = 4*(2*ModelTraits::dim());
503 static constexpr auto domainI = Dune::index_constant<id>();
504 static constexpr auto cellCenterId = GridGeometry::cellCenterIdx();
505 static constexpr auto faceId = GridGeometry::faceIdx();
506
507 static constexpr auto numEq = ModelTraits::numEq();
508 static constexpr auto numEqCellCenter = CellCenterPrimaryVariables::dimension;
509 static constexpr auto numEqFace = FacePrimaryVariables::dimension;
510
511public:
512 using ParentType::ParentType;
513
514 CellCenterResidualValue assembleCellCenterResidualImpl()
515 {
516 return this->evalLocalResidualForCellCenter();
517 }
518
519 FaceResidualValue assembleFaceResidualImpl(const SubControlVolumeFace& scvf)
520 {
521 return this->evalLocalResidualForFace(scvf);
522 }
523
530 template<class JacobianMatrixDiagBlock, class GridVariables>
531 CellCenterResidualValue assembleCellCenterJacobianAndResidualImpl(JacobianMatrixDiagBlock& A, GridVariables& gridVariables)
532 {
533 assert(domainI == cellCenterId);
534
535 // get some aliases for convenience
536 const auto& element = this->element();
537 const auto& fvGeometry = this->fvGeometry();
538 auto&& curElemVolVars = this->curElemVolVars();
539 const auto& gridGeometry = this->problem().gridGeometry();
540 const auto& curSol = this->curSol()[domainI];
541
542 const auto cellCenterGlobalI = gridGeometry.elementMapper().index(element);
543 const auto origResidual = this->evalLocalResidualForCellCenter();
544
546 // Calculate derivatives of all cell center residuals in the element w.r.t. to other cell center dofs. //
548
549 // lambda to evaluate the derivatives for cell center dofs with respect to neighbor cells
550 auto evaluateCellCenterDerivatives = [&](const std::size_t globalJ)
551 {
552 // get the volVars of the element with respect to which we are going to build the derivative
553 auto&& scvJ = fvGeometry.scv(globalJ);
554 const auto elementJ = fvGeometry.gridGeometry().element(globalJ);
555 auto& curVolVars = this->getVolVarAccess(gridVariables.curGridVolVars(), curElemVolVars, scvJ);
556 const auto origVolVars(curVolVars);
557
558 for (int pvIdx = 0; pvIdx < numEqCellCenter; ++pvIdx)
559 {
560 CellCenterPrimaryVariables cellCenterPriVars = curSol[globalJ];
561 using PrimaryVariables = typename VolumeVariables::PrimaryVariables;
562 PrimaryVariables priVars = makePriVarsFromCellCenterPriVars<PrimaryVariables>(cellCenterPriVars);
563
564 constexpr auto offset = numEq - numEqCellCenter;
565
566 auto evalResidual = [&](Scalar priVar)
567 {
568 // update the volume variables
569 priVars[pvIdx + offset] = priVar;
570 auto elemSol = elementSolution<FVElementGeometry>(std::move(priVars));
571 curVolVars.update(elemSol, this->problem(), elementJ, scvJ);
572
573 // update the coupling context
574 cellCenterPriVars[pvIdx] = priVar;
575 this->couplingManager().updateCouplingContext(domainI, *this, domainI, globalJ, cellCenterPriVars, pvIdx);
576
577 // compute element residual
578 return this->evalLocalResidualForCellCenter();
579 };
580
581 // create the vector storing the partial derivatives
582 CellCenterResidualValue partialDeriv(0.0);
583
584 // derive the residuals numerically
585 const auto& paramGroup = this->problem().paramGroup();
586 static const int numDiffMethod = getParamFromGroup<int>(paramGroup, "Assembly.NumericDifferenceMethod");
587 static const auto eps = this->couplingManager().numericEpsilon(domainI, paramGroup);
588 NumericDifferentiation::partialDerivative(evalResidual, priVars[pvIdx + offset], partialDeriv, origResidual,
589 eps(priVars[pvIdx + offset], pvIdx), numDiffMethod);
590
591 // update the global jacobian matrix with the current partial derivatives
592 updateGlobalJacobian_(A, cellCenterGlobalI, globalJ, pvIdx, partialDeriv);
593
594 // restore the original volVars
595 curVolVars = origVolVars;
596
597 // restore the undeflected state of the coupling context
598 this->couplingManager().updateCouplingContext(domainI, *this, domainI, globalJ, curSol[globalJ], pvIdx);
599 }
600 };
601
602 // get the list of cell center dofs that have an influence on the cell center resdiual of the current element
603 const auto& connectivityMap = gridGeometry.connectivityMap();
604
605 // evaluate derivatives w.r.t. own dof
606 evaluateCellCenterDerivatives(cellCenterGlobalI);
607
608 // evaluate derivatives w.r.t. all other related cell center dofs
609 for (const auto& globalJ : connectivityMap(cellCenterId, cellCenterId, cellCenterGlobalI))
610 evaluateCellCenterDerivatives(globalJ);
611
612 return origResidual;
613 }
614
621 template<class JacobianMatrixDiagBlock, class GridVariables>
622 auto assembleFaceJacobianAndResidualImpl(JacobianMatrixDiagBlock& A, GridVariables& gridVariables)
623 {
624 assert(domainI == faceId);
625
626 // get some aliases for convenience
627 const auto& problem = this->problem();
628 const auto& element = this->element();
629 const auto& fvGeometry = this->fvGeometry();
630 const auto& gridGeometry = this->problem().gridGeometry();
631 const auto& curSol = this->curSol()[domainI];
632
633 using FaceSolutionVector = GetPropType<TypeTag, Properties::FaceSolutionVector>; // TODO: use reserved vector
634 FaceSolutionVector origResiduals;
635 origResiduals.resize(fvGeometry.numScvf());
636 origResiduals = 0.0;
637
638 // treat the local residua of the face dofs:
639 for (auto&& scvf : scvfs(fvGeometry))
640 origResiduals[scvf.localFaceIdx()] = this->evalLocalResidualForFace(scvf);
641
643 // Calculate derivatives of all face residuals in the element w.r.t. to other face dofs. //
644 // Note that we do an element-wise assembly, therefore this is only the contribution of the //
645 // current element while the contribution of the element on the opposite side of the scvf will //
646 // be added separately. //
648
649 for (auto&& scvf : scvfs(fvGeometry))
650 {
651 // set the actual dof index
652 const auto faceGlobalI = scvf.dofIndex();
653
655 const auto origFaceSolution = FaceSolution(scvf, curSol, gridGeometry);
656
657 // Lambda to evaluate the derivatives for faces
658 auto evaluateFaceDerivatives = [&](const std::size_t globalJ)
659 {
660 // get the faceVars of the face with respect to which we are going to build the derivative
661 auto& faceVars = getFaceVarAccess_(gridVariables.curGridFaceVars(), this->curElemFaceVars(), scvf);
662 const auto origFaceVars = faceVars;
663
664 for (int pvIdx = 0; pvIdx < numEqFace; ++pvIdx)
665 {
666 auto faceSolution = origFaceSolution;
667
668 auto evalResidual = [&](Scalar priVar)
669 {
670 // update the volume variables
671 faceSolution[globalJ][pvIdx] = priVar;
672 faceVars.update(faceSolution, problem, element, fvGeometry, scvf);
673
674 // update the coupling context
675 this->couplingManager().updateCouplingContext(domainI, *this, domainI, globalJ, faceSolution[globalJ], pvIdx);
676
677 // compute face residual
678 return this->evalLocalResidualForFace(scvf);
679 };
680
681 // derive the residuals numerically
682 FaceResidualValue partialDeriv(0.0);
683 const auto& paramGroup = problem.paramGroup();
684 static const int numDiffMethod = getParamFromGroup<int>(paramGroup, "Assembly.NumericDifferenceMethod");
685 static const auto eps = this->couplingManager().numericEpsilon(domainI, paramGroup);
686 NumericDifferentiation::partialDerivative(evalResidual, faceSolution[globalJ][pvIdx], partialDeriv, origResiduals[scvf.localFaceIdx()],
687 eps(faceSolution[globalJ][pvIdx], pvIdx), numDiffMethod);
688
689 // update the global jacobian matrix with the current partial derivatives
690 updateGlobalJacobian_(A, faceGlobalI, globalJ, pvIdx, partialDeriv);
691
692 // restore the original faceVars
693 faceVars = origFaceVars;
694
695 // restore the undeflected state of the coupling context
696 this->couplingManager().updateCouplingContext(domainI, *this, domainI, globalJ, origFaceSolution[globalJ], pvIdx);
697 }
698 };
699
700 // evaluate derivatives w.r.t. own dof
701 evaluateFaceDerivatives(scvf.dofIndex());
702
703 // get the list of face dofs that have an influence on the resdiual of the current face
704 const auto& connectivityMap = gridGeometry.connectivityMap();
705
706 // evaluate derivatives w.r.t. all other related face dofs
707 for (const auto& globalJ : connectivityMap(faceId, faceId, scvf.index()))
708 evaluateFaceDerivatives(globalJ);
709 }
710
711 return origResiduals;
712 }
713
720 template<class JacobianBlock, class GridVariables>
721 void assembleJacobianCellCenterCoupling(Dune::index_constant<faceId> domainJ, JacobianBlock& A,
722 const CellCenterResidualValue& origResidual, GridVariables& gridVariables)
723 {
725 // Calculate derivatives of all cell center residuals in the element w.r.t. to all coupled faces dofs //
727
728 // get some aliases for convenience
729 const auto& element = this->element();
730 const auto& fvGeometry = this->fvGeometry();
731 const auto& gridGeometry = this->problem().gridGeometry();
732 const auto& curSol = this->curSol()[domainJ];
733 // build derivatives with for cell center dofs w.r.t. cell center dofs
734 const auto cellCenterGlobalI = gridGeometry.elementMapper().index(element);
735
736 for (const auto& scvfJ : scvfs(fvGeometry))
737 {
738 const auto globalJ = scvfJ.dofIndex();
739
740 // get the faceVars of the face with respect to which we are going to build the derivative
741 auto& faceVars = getFaceVarAccess_(gridVariables.curGridFaceVars(), this->curElemFaceVars(), scvfJ);
742 const auto origFaceVars(faceVars);
743
744 for (int pvIdx = 0; pvIdx < numEqFace; ++pvIdx)
745 {
746 auto facePriVars = curSol[globalJ];
747
748 auto evalResidual = [&](Scalar priVar)
749 {
750 // update the face variables
751 facePriVars[pvIdx] = priVar;
752 faceVars.updateOwnFaceOnly(facePriVars);
753
754 // update the coupling context
755 this->couplingManager().updateCouplingContext(domainI, *this, domainJ, globalJ, facePriVars, pvIdx);
756
757 // compute element residual
758 return this->evalLocalResidualForCellCenter();
759 };
760
761 // create the vector storing the partial derivatives
762 CellCenterResidualValue partialDeriv(0.0);
763
764 // derive the residuals numerically
765 const auto& paramGroup = this->assembler().problem(domainJ).paramGroup();
766 static const int numDiffMethod = getParamFromGroup<int>(paramGroup, "Assembly.NumericDifferenceMethod");
767 static const auto epsCoupl = this->couplingManager().numericEpsilon(domainJ, paramGroup);
768 NumericDifferentiation::partialDerivative(evalResidual, facePriVars[pvIdx], partialDeriv, origResidual,
769 epsCoupl(facePriVars[pvIdx], pvIdx), numDiffMethod);
770
771 // update the global jacobian matrix with the current partial derivatives
772 updateGlobalJacobian_(A, cellCenterGlobalI, globalJ, pvIdx, partialDeriv);
773
774 // restore the original faceVars
775 faceVars = origFaceVars;
776
777 // restore the undeflected state of the coupling context
778 this->couplingManager().updateCouplingContext(domainI, *this, domainJ, globalJ, curSol[globalJ], pvIdx);
779 }
780 }
781 }
782
783 template<std::size_t otherId, class JacobianBlock, class GridVariables>
784 void assembleJacobianCellCenterCoupling(Dune::index_constant<otherId> domainJ, JacobianBlock& A,
785 const CellCenterResidualValue& res, GridVariables& gridVariables)
786 {
788 // Calculate derivatives of all cell center residuals in the element w.r.t. all dofs in the coupling stencil. //
790
791 // get some aliases for convenience
792 const auto& element = this->element();
793
794 // get stencil informations
795 const auto& stencil = this->couplingManager().couplingStencil(domainI, element, domainJ);
796
797 if (stencil.empty())
798 return;
799
800 for (const auto globalJ : stencil)
801 {
802 const auto origResidual = this->couplingManager().evalCouplingResidual(domainI, *this, domainJ, globalJ);
803 const auto& curSol = this->curSol()[domainJ];
804 const auto origPriVarsJ = curSol[globalJ];
805
806 for (int pvIdx = 0; pvIdx < JacobianBlock::block_type::cols; ++pvIdx)
807 {
808 auto evalCouplingResidual = [&](Scalar priVar)
809 {
810 auto deflectedPriVarsJ = origPriVarsJ;
811 deflectedPriVarsJ[pvIdx] = priVar;
812 this->couplingManager().updateCouplingContext(domainI, *this, domainJ, globalJ, deflectedPriVarsJ, pvIdx);
813 return this->couplingManager().evalCouplingResidual(domainI, *this, domainJ, globalJ);
814 };
815
816 // create the vector storing the partial derivatives
817 CellCenterResidualValue partialDeriv(0.0);
818
819 // derive the residuals numerically
820 const auto& paramGroup = this->assembler().problem(domainJ).paramGroup();
821 static const int numDiffMethod = getParamFromGroup<int>(paramGroup, "Assembly.NumericDifferenceMethod");
822 static const auto epsCoupl = this->couplingManager().numericEpsilon(domainJ, paramGroup);
823 NumericDifferentiation::partialDerivative(evalCouplingResidual, origPriVarsJ[pvIdx], partialDeriv, origResidual,
824 epsCoupl(origPriVarsJ[pvIdx], pvIdx), numDiffMethod);
825
826 // update the global stiffness matrix with the current partial derivatives
827 const auto cellCenterGlobalI = this->problem().gridGeometry().elementMapper().index(element);
828 updateGlobalJacobian_(A, cellCenterGlobalI, globalJ, pvIdx, partialDeriv);
829
830 // restore the undeflected state of the coupling context
831 this->couplingManager().updateCouplingContext(domainI, *this, domainJ, globalJ, origPriVarsJ, pvIdx);
832 }
833 }
834 }
835
842 template<class JacobianBlock, class ElementResidualVector, class GridVariables>
843 void assembleJacobianFaceCoupling(Dune::index_constant<cellCenterId> domainJ, JacobianBlock& A,
844 const ElementResidualVector& origResiduals, GridVariables& gridVariables)
845 {
847 // Calculate derivatives of all face residuals in the element w.r.t. all coupled cell center dofs //
849
850 // get some aliases for convenience
851 const auto& problem = this->problem();
852 const auto& fvGeometry = this->fvGeometry();
853 const auto& gridGeometry = this->problem().gridGeometry();
854 const auto& connectivityMap = gridGeometry.connectivityMap();
855 const auto& curSol = this->curSol()[domainJ];
856
857 // build derivatives with for cell center dofs w.r.t. cell center dofs
858 for (auto&& scvf : scvfs(fvGeometry))
859 {
860 // set the actual dof index
861 const auto faceGlobalI = scvf.dofIndex();
862
863 // build derivatives with for face dofs w.r.t. cell center dofs
864 for (const auto& globalJ : connectivityMap(faceId, cellCenterId, scvf.index()))
865 {
866 // get the volVars of the element with respect to which we are going to build the derivative
867 auto&& scvJ = fvGeometry.scv(globalJ);
868 const auto elementJ = fvGeometry.gridGeometry().element(globalJ);
869 auto& curVolVars = this->getVolVarAccess(gridVariables.curGridVolVars(), this->curElemVolVars(), scvJ);
870 const auto origVolVars(curVolVars);
871 const auto origCellCenterPriVars = curSol[globalJ];
872
873 for (int pvIdx = 0; pvIdx < numEqCellCenter; ++pvIdx)
874 {
875 using PrimaryVariables = typename VolumeVariables::PrimaryVariables;
876 PrimaryVariables priVars = makePriVarsFromCellCenterPriVars<PrimaryVariables>(origCellCenterPriVars);
877
878 constexpr auto offset = PrimaryVariables::dimension - CellCenterPrimaryVariables::dimension;
879
880 auto evalResidual = [&](Scalar priVar)
881 {
882 // update the volume variables
883 priVars[pvIdx + offset] = priVar;
884 auto elemSol = elementSolution<FVElementGeometry>(std::move(priVars));
885 curVolVars.update(elemSol, problem, elementJ, scvJ);
886
887 // update the coupling context
888 auto deflectedCellCenterPriVars = origCellCenterPriVars;
889 deflectedCellCenterPriVars[pvIdx] = priVar;
890 this->couplingManager().updateCouplingContext(domainI, *this, domainJ, globalJ, deflectedCellCenterPriVars, pvIdx);
891
892 // compute face residual
893 return this->evalLocalResidualForFace(scvf);
894 };
895
896 // derive the residuals numerically
897 FaceResidualValue partialDeriv(0.0);
898 const auto& paramGroup = this->assembler().problem(domainJ).paramGroup();
899 static const int numDiffMethod = getParamFromGroup<int>(paramGroup, "Assembly.NumericDifferenceMethod");
900 static const auto epsCoupl = this->couplingManager().numericEpsilon(domainJ, paramGroup);
901 NumericDifferentiation::partialDerivative(evalResidual, priVars[pvIdx + offset], partialDeriv, origResiduals[scvf.localFaceIdx()],
902 epsCoupl(priVars[pvIdx + offset], pvIdx), numDiffMethod);
903
904 // update the global jacobian matrix with the current partial derivatives
905 updateGlobalJacobian_(A, faceGlobalI, globalJ, pvIdx, partialDeriv);
906
907 // restore the original volVars
908 curVolVars = origVolVars;
909
910 // restore the undeflected state of the coupling context
911 this->couplingManager().updateCouplingContext(domainI, *this, domainJ, globalJ, origCellCenterPriVars, pvIdx);
912 }
913 }
914 }
915 }
916
917 template<std::size_t otherId, class JacobianBlock, class ElementResidualVector, class GridVariables>
918 void assembleJacobianFaceCoupling(Dune::index_constant<otherId> domainJ, JacobianBlock& A,
919 const ElementResidualVector& res, GridVariables& gridVariables)
920 {
922 // Calculate derivatives of all face residuals in the element w.r.t. all dofs in the coupling stencil. //
924
925 // get some aliases for convenience
926 const auto& fvGeometry = this->fvGeometry();
927 const auto& curSol = this->curSol()[domainJ];
928
929 // build derivatives with for cell center dofs w.r.t. cell center dofs
930 for (auto&& scvf : scvfs(fvGeometry))
931 {
932 // set the actual dof index
933 const auto faceGlobalI = scvf.dofIndex();
934
935 // get stencil informations
936 const auto& stencil = this->couplingManager().couplingStencil(domainI, scvf, domainJ);
937
938 if (stencil.empty())
939 continue;
940
941 // build derivatives with for face dofs w.r.t. cell center dofs
942 for (const auto& globalJ : stencil)
943 {
944 const auto origPriVarsJ = curSol[globalJ];
945 const auto origResidual = this->couplingManager().evalCouplingResidual(domainI, scvf, *this, domainJ, globalJ);
946
947 for (int pvIdx = 0; pvIdx < JacobianBlock::block_type::cols; ++pvIdx)
948 {
949 auto evalCouplingResidual = [&](Scalar priVar)
950 {
951 auto deflectedPriVars = origPriVarsJ;
952 deflectedPriVars[pvIdx] = priVar;
953 this->couplingManager().updateCouplingContext(domainI, *this, domainJ, globalJ, deflectedPriVars, pvIdx);
954 return this->couplingManager().evalCouplingResidual(domainI, scvf, *this, domainJ, globalJ);
955 };
956
957 // derive the residuals numerically
958 FaceResidualValue partialDeriv(0.0);
959 const auto& paramGroup = this->assembler().problem(domainJ).paramGroup();
960 static const int numDiffMethod = getParamFromGroup<int>(paramGroup, "Assembly.NumericDifferenceMethod");
961 static const auto epsCoupl = this->couplingManager().numericEpsilon(domainJ, paramGroup);
962 NumericDifferentiation::partialDerivative(evalCouplingResidual, origPriVarsJ[pvIdx], partialDeriv, origResidual,
963 epsCoupl(origPriVarsJ[pvIdx], pvIdx), numDiffMethod);
964
965 // update the global stiffness matrix with the current partial derivatives
966 updateGlobalJacobian_(A, faceGlobalI, globalJ, pvIdx, partialDeriv);
967
968 // restore the undeflected state of the coupling context
969 this->couplingManager().updateCouplingContext(domainI, *this, domainJ, globalJ, origPriVarsJ, pvIdx);
970 }
971 }
972 }
973 }
974
975 template<class JacobianMatrixDiagBlock, class GridVariables>
976 void evalAdditionalDerivatives(const std::vector<std::size_t>& additionalDofDependencies,
977 JacobianMatrixDiagBlock& A, GridVariables& gridVariables)
978 { }
979
985 template<class SubMatrix, class CCOrFacePrimaryVariables>
986 static void updateGlobalJacobian_(SubMatrix& matrix,
987 const int globalI,
988 const int globalJ,
989 const int pvIdx,
990 const CCOrFacePrimaryVariables& partialDeriv)
991 {
992 for (int eqIdx = 0; eqIdx < partialDeriv.size(); eqIdx++)
993 {
994 // A[i][col][eqIdx][pvIdx] is the rate of change of
995 // the residual of equation 'eqIdx' at dof 'i'
996 // depending on the primary variable 'pvIdx' at dof
997 // 'col'.
998
999 assert(pvIdx >= 0);
1000 assert(eqIdx < matrix[globalI][globalJ].size());
1001 assert(pvIdx < matrix[globalI][globalJ][eqIdx].size());
1002 matrix[globalI][globalJ][eqIdx][pvIdx] += partialDeriv[eqIdx];
1003 }
1004 }
1005
1006private:
1007
1008 FaceVariables& getFaceVarAccess_(GridFaceVariables& gridFaceVariables, ElementFaceVariables& elemFaceVars, const SubControlVolumeFace& scvf)
1009 {
1011 return gridFaceVariables.faceVars(scvf.index());
1012 else
1013 return elemFaceVars[scvf];
1014 }
1015};
1016
1017} // end namespace Dumux
1018
1019#endif
A base class for all local assemblers.
An enum class to define various differentiation methods available in order to compute the derivatives...
Utilities for template meta programming.
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
A arithmetic block vector type based on DUNE's reserved vector.
A class for numeric differentiation.
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition localview.hh:38
auto elementSolution(const Element &element, const SolutionVector &sol, const GridGeometry &gg) -> std::enable_if_t< GridGeometry::discMethod==DiscretizationMethod::box, BoxElementSolution< typename GridGeometry::LocalView, std::decay_t< decltype(std::declval< SolutionVector >()[0])> > >
Make an element solution for box schemes.
Definition box/elementsolution.hh:118
PrimaryVariables makePriVarsFromCellCenterPriVars(const CellCenterPrimaryVariables &cellCenterPriVars)
Helper function to create a PrimaryVariables object from CellCenterPrimaryVariables.
Definition staggered/elementsolution.hh:41
DiffMethod
Differentiation methods in order to compute the derivatives of the residual i.e. the entries in the j...
Definition diffmethod.hh:37
@ numeric
Definition diffmethod.hh:38
T getParamFromGroup(Args &&... args)
A free function to get a parameter from the parameter tree singleton with a model group.
Definition parameters.hh:358
Definition adapt.hh:29
constexpr auto getPropValue()
get the value data member of a property
Definition propertysystem.hh:154
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property
Definition propertysystem.hh:150
typename Detail::ConcatSeq< decltype(std::make_index_sequence< e >{}), e+1, decltype(std::make_index_sequence<(n > e) ?(n - e - 1) :0 >{})>::type makeIncompleteIntegerSequence
Definition utility.hh:70
Definition common/pdesolver.hh:36
ElementVolumeVariables & curElemVolVars()
Definition fvlocalassemblerbase.hh:265
ElementBoundaryTypes & elemBcTypes()
Definition fvlocalassemblerbase.hh:281
Implementation & asImp_()
Definition fvlocalassemblerbase.hh:309
ElementVolumeVariables & prevElemVolVars()
Definition fvlocalassemblerbase.hh:269
FVLocalAssemblerBase(const Assembler &assembler, const Element &element, const SolutionVector &curSol)
Definition fvlocalassemblerbase.hh:73
FVElementGeometry & fvGeometry()
Definition fvlocalassemblerbase.hh:261
const Assembler & assembler() const
Definition fvlocalassemblerbase.hh:245
ElementFluxVariablesCache & elemFluxVarsCache()
Definition fvlocalassemblerbase.hh:273
bool elementIsGhost() const
Definition fvlocalassemblerbase.hh:253
LocalResidual & localResidual()
Definition fvlocalassemblerbase.hh:277
static constexpr bool isImplicit()
Definition fvlocalassemblerbase.hh:113
const Element & element() const
Definition fvlocalassemblerbase.hh:249
VolumeVariables & getVolVarAccess(GridVolumeVariables &gridVolVars, ElementVolumeVariables &elemVolVars, const SubControlVolume &scv)
Definition fvlocalassemblerbase.hh:316
const SolutionVector & curSol() const
Definition fvlocalassemblerbase.hh:257
static void partialDerivative(const Function &function, Scalar x0, FunctionEvalType &derivative, const FunctionEvalType &fx0, const int numericDifferenceMethod=1)
Computes the derivative of a function with repect to a function parameter.
Definition numericdifferentiation.hh:61
FaceResidualValue evalLocalResidualForFace(const SubControlVolumeFace &scvf) const
Convenience function to evaluate the local residual for the current face. Automatically chooses the t...
Definition subdomainstaggeredlocalassembler.hh:229
const ElementFaceVariables & curElemFaceVars() const
The current element volume variables.
Definition subdomainstaggeredlocalassembler.hh:315
FaceResidualValue evalLocalFluxAndSourceResidualForFace(const SubControlVolumeFace &scvf, const ElementVolumeVariables &elemVolVars, const ElementFaceVariables &elemFaceVars) const
Evaluates the flux and source terms (i.e, the terms without a time derivative) of the local residual ...
Definition subdomainstaggeredlocalassembler.hh:285
void assembleJacobianAndResidual(JacobianMatrixRow &jacRow, SubSol &res, GridVariablesTuple &gridVariables)
Computes the derivatives with respect to the given element and adds them to the global matrix....
Definition subdomainstaggeredlocalassembler.hh:117
ElementFaceVariables & prevElemFaceVars()
The element volume variables of the provious time step.
Definition subdomainstaggeredlocalassembler.hh:311
static constexpr auto domainId
Definition subdomainstaggeredlocalassembler.hh:85
void assembleResidual(SubSol &res)
Assemble the residual only.
Definition subdomainstaggeredlocalassembler.hh:129
const Problem & problem() const
Definition subdomainstaggeredlocalassembler.hh:303
SubDomainStaggeredLocalAssemblerBase(const Assembler &assembler, const Element &element, const SolutionVector &curSol, CouplingManager &couplingManager)
Definition subdomainstaggeredlocalassembler.hh:94
FaceResidualValue evalLocalFluxAndSourceResidualForFace(const SubControlVolumeFace &scvf) const
Convenience function to evaluate the flux and source terms (i.e, the terms without a time derivative)...
Definition subdomainstaggeredlocalassembler.hh:272
CellCenterResidualValue evalLocalFluxAndSourceResidualForCellCenter() const
Convenience function to evaluate the flux and source terms (i.e, the terms without a time derivative)...
Definition subdomainstaggeredlocalassembler.hh:196
static constexpr auto faceId
Definition subdomainstaggeredlocalassembler.hh:87
static constexpr auto faceOffset
Definition subdomainstaggeredlocalassembler.hh:90
FaceResidualValue evalLocalResidualForFace(const SubControlVolumeFace &scvf, const ElementVolumeVariables &elemVolVars, const ElementFaceVariables &elemFaceVars) const
Evaluates the complete local residual for the current face.
Definition subdomainstaggeredlocalassembler.hh:250
static constexpr auto numEqCellCenter
Definition subdomainstaggeredlocalassembler.hh:89
const ElementFaceVariables & prevElemFaceVars() const
The element volume variables of the provious time step.
Definition subdomainstaggeredlocalassembler.hh:319
CellCenterResidualValue evalLocalResidualForCellCenter() const
Convenience function to evaluate the complete local residual for the current element....
Definition subdomainstaggeredlocalassembler.hh:150
FaceResidualValue evalLocalStorageResidualForFace(const SubControlVolumeFace &scvf) const
Convenience function to evaluate storage term (i.e, the term with a time derivative) of the local res...
Definition subdomainstaggeredlocalassembler.hh:298
CouplingManager & couplingManager()
Definition subdomainstaggeredlocalassembler.hh:322
static constexpr auto cellCenterId
Definition subdomainstaggeredlocalassembler.hh:86
CellCenterResidualValue evalLocalResidualForCellCenter(const ElementVolumeVariables &elemVolVars, const ElementFaceVariables &elemFaceVars) const
Evaluates the complete local residual for the current cell center.
Definition subdomainstaggeredlocalassembler.hh:170
CellCenterResidualValue evalLocalFluxAndSourceResidualForCellCenter(const ElementVolumeVariables &elemVolVars, const ElementFaceVariables &elemFaceVars) const
Evaluates the flux and source terms (i.e, the terms without a time derivative) of the local residual ...
Definition subdomainstaggeredlocalassembler.hh:209
CellCenterResidualValue evalLocalStorageResidualForCellCenter() const
Convenience function to evaluate storage term (i.e, the term with a time derivative) of the local res...
Definition subdomainstaggeredlocalassembler.hh:219
ElementFaceVariables & curElemFaceVars()
The current element volume variables.
Definition subdomainstaggeredlocalassembler.hh:307
A base class for all implicit multidomain local assemblers (staggered).
Definition subdomainstaggeredlocalassembler.hh:413
void bindLocalViews()
Definition subdomainstaggeredlocalassembler.hh:419
The staggered multidomain local assembler.
Definition subdomainstaggeredlocalassembler.hh:456
void assembleJacobianFaceCoupling(Dune::index_constant< cellCenterId > domainJ, JacobianBlock &A, const ElementResidualVector &origResiduals, GridVariables &gridVariables)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition subdomainstaggeredlocalassembler.hh:843
void assembleJacobianFaceCoupling(Dune::index_constant< otherId > domainJ, JacobianBlock &A, const ElementResidualVector &res, GridVariables &gridVariables)
Definition subdomainstaggeredlocalassembler.hh:918
FaceResidualValue assembleFaceResidualImpl(const SubControlVolumeFace &scvf)
Definition subdomainstaggeredlocalassembler.hh:519
CellCenterResidualValue assembleCellCenterJacobianAndResidualImpl(JacobianMatrixDiagBlock &A, GridVariables &gridVariables)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition subdomainstaggeredlocalassembler.hh:531
void assembleJacobianCellCenterCoupling(Dune::index_constant< faceId > domainJ, JacobianBlock &A, const CellCenterResidualValue &origResidual, GridVariables &gridVariables)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition subdomainstaggeredlocalassembler.hh:721
CellCenterResidualValue assembleCellCenterResidualImpl()
Definition subdomainstaggeredlocalassembler.hh:514
static void updateGlobalJacobian_(SubMatrix &matrix, const int globalI, const int globalJ, const int pvIdx, const CCOrFacePrimaryVariables &partialDeriv)
Updates the current global Jacobian matrix with the partial derivatives of all equations in regard to...
Definition subdomainstaggeredlocalassembler.hh:986
void evalAdditionalDerivatives(const std::vector< std::size_t > &additionalDofDependencies, JacobianMatrixDiagBlock &A, GridVariables &gridVariables)
Definition subdomainstaggeredlocalassembler.hh:976
auto assembleFaceJacobianAndResidualImpl(JacobianMatrixDiagBlock &A, GridVariables &gridVariables)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition subdomainstaggeredlocalassembler.hh:622
void assembleJacobianCellCenterCoupling(Dune::index_constant< otherId > domainJ, JacobianBlock &A, const CellCenterResidualValue &res, GridVariables &gridVariables)
Definition subdomainstaggeredlocalassembler.hh:784
The local element solution class for staggered methods.
Declares all properties used in Dumux.