version 3.11-dev
Loading...
Searching...
No Matches
subdomainfclocalassembler.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-FileCopyrightText: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
14#ifndef DUMUX_MULTIDOMAIN_FACECENTERED_LOCAL_ASSEMBLER_HH
15#define DUMUX_MULTIDOMAIN_FACECENTERED_LOCAL_ASSEMBLER_HH
16
17#include <dune/common/indices.hh>
18#include <dune/common/hybridutilities.hh>
19#include <dune/grid/common/gridenums.hh>
20
27
28namespace Dumux {
29
41template<std::size_t id, class TypeTag, class Assembler, class Implementation, DiffMethod dm, bool implicit>
42class SubDomainFaceCenteredLocalAssemblerBase : public FaceCenteredLocalAssembler<TypeTag, Assembler, dm, implicit, Implementation>
43{
45
47 using SolutionVector = typename Assembler::SolutionVector;
48
50 using GridVolumeVariables = typename GridVariables::GridVolumeVariables;
51 using ElementVolumeVariables = typename GridVolumeVariables::LocalView;
52 using ElementFluxVariablesCache = typename GridVariables::GridFluxVariablesCache::LocalView;
53 using Scalar = typename GridVariables::Scalar;
54
55 using GridGeometry = typename GridVariables::GridGeometry;
56 using FVElementGeometry = typename GridGeometry::LocalView;
57 using SubControlVolume = typename GridGeometry::SubControlVolume;
58 using GridView = typename GridGeometry::GridView;
59 using Element = typename GridView::template Codim<0>::Entity;
60
61 using CouplingManager = typename Assembler::CouplingManager;
62
63 static constexpr auto numEq = GetPropType<TypeTag, Properties::ModelTraits>::numEq();
64
65public:
67 static constexpr auto domainId = typename Dune::index_constant<id>();
69 using ParentType::ParentType;
71 using ElementResidualVector = typename ParentType::LocalResidual::ElementResidualVector;
72
73 // the constructor
74 explicit SubDomainFaceCenteredLocalAssemblerBase(const Assembler& assembler,
75 const Element& element,
76 const SolutionVector& curSol,
77 CouplingManager& couplingManager)
78 : ParentType(assembler,
79 element,
80 curSol,
81 localView(assembler.gridGeometry(domainId)),
82 localView(assembler.gridVariables(domainId).curGridVolVars()),
83 localView(assembler.gridVariables(domainId).prevGridVolVars()),
84 localView(assembler.gridVariables(domainId).gridFluxVarsCache()),
85 assembler.localResidual(domainId),
86 (element.partitionType() == Dune::GhostEntity))
87 , couplingManager_(couplingManager)
88 {}
89
94 template<class JacobianMatrixRow, class SubResidualVector, class GridVariablesTuple>
95 void assembleJacobianAndResidual(JacobianMatrixRow& jacRow, SubResidualVector& res, GridVariablesTuple& gridVariables)
96 {
97 auto assembleCouplingBlocks = [&](const auto& residual)
98 {
99 // assemble the coupling blocks
100 using namespace Dune::Hybrid;
101 forEach(integralRange(Dune::Hybrid::size(jacRow)), [&](auto&& i)
102 {
103 if (i != id)
104 this->assembleJacobianCoupling(i, jacRow, residual, gridVariables);
105 });
106 };
107
108 // the coupled model does not support partial reassembly yet
109 const DefaultPartialReassembler* noReassembler = nullptr;
110 ParentType::assembleJacobianAndResidual(jacRow[domainId], res, *std::get<domainId>(gridVariables), noReassembler, assembleCouplingBlocks);
111 }
112
117 template<std::size_t otherId, class JacRow, class GridVariables,
118 typename std::enable_if_t<(otherId == id), int> = 0>
119 void assembleJacobianCoupling(Dune::index_constant<otherId> domainJ, JacRow& jacRow,
120 const ElementResidualVector& res, GridVariables& gridVariables)
121 {}
122
126 template<std::size_t otherId, class JacRow, class GridVariables,
127 typename std::enable_if_t<(otherId != id), int> = 0>
128 void assembleJacobianCoupling(Dune::index_constant<otherId> domainJ, JacRow& jacRow,
129 const ElementResidualVector& res, GridVariables& gridVariables)
130 {
131 this->asImp_().assembleJacobianCoupling(domainJ, jacRow[domainJ], res, *std::get<domainId>(gridVariables));
132 }
133
137 ElementResidualVector evalLocalSourceResidual(const Element& element, const ElementVolumeVariables& elemVolVars) const
138 {
139 // initialize the residual vector for all scvs in this element
140 ElementResidualVector residual(this->fvGeometry().numScv());
141
142 // evaluate the volume terms (storage + source terms)
143 // forward to the local residual specialized for the discretization methods
144 for (auto&& scv : scvs(this->fvGeometry()))
145 {
146 const auto& curVolVars = elemVolVars[scv];
147 auto source = this->localResidual().computeSource(problem(), element, this->fvGeometry(), elemVolVars, scv);
148 source *= -scv.volume()*curVolVars.extrusionFactor();
149 residual[scv.localDofIndex()] = std::move(source);
150 }
151
152 return residual;
153 }
154
158 ElementResidualVector evalLocalSourceResidual(const Element& neighbor) const
159 { return this->evalLocalSourceResidual(neighbor, implicit ? this->curElemVolVars() : this->prevElemVolVars()); }
160
165 {
166 // get some references for convenience
167 const auto& element = this->element();
168 const auto& curSol = this->curSol(domainId);
169 auto&& fvGeometry = this->fvGeometry();
170 auto&& curElemVolVars = this->curElemVolVars();
171 auto&& elemFluxVarsCache = this->elemFluxVarsCache();
172
173 // bind the caches
174 couplingManager_.bindCouplingContext(domainId, element, this->assembler());
175 fvGeometry.bind(element);
176
177 if (implicit)
178 {
179 curElemVolVars.bind(element, fvGeometry, curSol);
180 elemFluxVarsCache.bind(element, fvGeometry, curElemVolVars);
181 if (!this->assembler().isStationaryProblem())
182 this->prevElemVolVars().bindElement(element, fvGeometry, this->assembler().prevSol()[domainId]);
183 }
184 else
185 {
186 auto& prevElemVolVars = this->prevElemVolVars();
187 const auto& prevSol = this->assembler().prevSol()[domainId];
188
189 curElemVolVars.bindElement(element, fvGeometry, curSol);
190 prevElemVolVars.bind(element, fvGeometry, prevSol);
191 elemFluxVarsCache.bind(element, fvGeometry, prevElemVolVars);
192 }
193
194 this->elemBcTypes().update(problem(), this->element(), this->fvGeometry());
195 }
196
198 template<std::size_t i = domainId>
199 const Problem& problem(Dune::index_constant<i> dId = domainId) const
200 { return this->assembler().problem(domainId); }
201
203 template<std::size_t i = domainId>
204 const auto& curSol(Dune::index_constant<i> dId = domainId) const
205 { return ParentType::curSol()[dId]; }
206
208 CouplingManager& couplingManager()
209 { return couplingManager_; }
210
211private:
212 CouplingManager& couplingManager_;
213};
214
226template<std::size_t id, class TypeTag, class Assembler, DiffMethod DM = DiffMethod::numeric, bool implicit = true>
228
235template<std::size_t id, class TypeTag, class Assembler>
236class SubDomainFaceCenteredLocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, /*implicit=*/true>
238 id, TypeTag, Assembler,
240 DiffMethod::numeric, /*implicit=*/true
241>
242{
243 using ThisType = SubDomainFaceCenteredLocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, /*implicit=*/true>;
244 using ParentType = SubDomainFaceCenteredLocalAssemblerBase<id, TypeTag, Assembler, ThisType, DiffMethod::numeric, /*implicit=*/true>;
247
249 using FVElementGeometry = typename GridGeometry::LocalView;
250 using GridView = typename GridGeometry::GridView;
251 using Element = typename GridView::template Codim<0>::Entity;
252 using SubControlVolume = typename FVElementGeometry::SubControlVolume;
253
255 enum { dim = GridView::dimension };
256
259 static constexpr auto domainI = Dune::index_constant<id>();
260
261public:
262 using ParentType::ParentType;
265
269 template<class ElemSol>
270 void maybeUpdateCouplingContext(const SubControlVolume& scv, ElemSol& elemSol, const int pvIdx)
271 {
272 this->couplingManager().updateCouplingContext(domainI, *this, domainI, scv.dofIndex(), elemSol[scv.localDofIndex()], pvIdx);
273 }
274
278 template<class JacobianMatrixDiagBlock, class GridVariables>
279 void maybeEvalAdditionalDomainDerivatives(const ElementResidualVector& origResiduals, const JacobianMatrixDiagBlock& A, GridVariables& gridVariables)
280 {
281 this->couplingManager().evalAdditionalDomainDerivatives(domainI, *this, origResiduals, A, gridVariables);
282 }
283
288 template<std::size_t otherId, class JacobianBlock, class GridVariables>
289 void assembleJacobianCoupling(Dune::index_constant<otherId> domainJ, JacobianBlock& A,
290 const ElementResidualVector& res, GridVariables& gridVariables)
291 {
293 // Calculate derivatives of all dofs in the element with respect to all dofs in the coupling stencil. //
295
296 // get some aliases for convenience
297 const auto& element = this->element();
298 const auto& fvGeometry = this->fvGeometry();
299 auto&& curElemVolVars = this->curElemVolVars();
300 auto&& elemFluxVarsCache = this->elemFluxVarsCache();
301
302 // the solution vector of the other domain
303 const auto& curSolJ = this->curSol(domainJ);
304
305 // convenience lambda for call to update self
306 auto updateCoupledVariables = [&] ()
307 {
308 // Update ourself after the context has been modified. Depending on the
309 // type of caching, other objects might have to be updated. All ifs can be optimized away.
310 if constexpr (enableGridFluxVarsCache)
311 {
312 if constexpr (enableGridVolVarsCache)
313 this->couplingManager().updateCoupledVariables(domainI, *this, gridVariables.curGridVolVars(), gridVariables.gridFluxVarsCache());
314 else
315 this->couplingManager().updateCoupledVariables(domainI, *this, curElemVolVars, gridVariables.gridFluxVarsCache());
316 }
317 else
318 {
319 if constexpr (enableGridVolVarsCache)
320 this->couplingManager().updateCoupledVariables(domainI, *this, gridVariables.curGridVolVars(), elemFluxVarsCache);
321 else
322 this->couplingManager().updateCoupledVariables(domainI, *this, curElemVolVars, elemFluxVarsCache);
323 }
324 };
325
326 const bool interiorElement = element.partitionType() == Dune::InteriorEntity;
327 for (const auto& scv : scvs(fvGeometry))
328 {
329 // of an overlap element only the border dofs have assembled equations, the others have identity rows
330 if (!interiorElement && element.template subEntity<1>(scv.indexInElement()).partitionType() != Dune::BorderEntity)
331 continue;
332
333 // the equation of a dof with an internal Dirichlet constraint does not depend on the other domain
334 if constexpr (Problem::enableInternalDirichletConstraints())
335 {
336 if (this->internalDirichletValue(scv))
337 continue;
338 }
339
340 const auto& stencil = this->couplingManager().couplingStencil(domainI, element, scv, domainJ);
341
342 for (const auto globalJ : stencil)
343 {
344 const auto origResidual = this->couplingManager().evalCouplingResidual(domainI, *this, scv, domainJ, globalJ); // TODO is this necessary?
345 // undeflected privars and privars to be deflected
346 const auto origPriVarsJ = curSolJ[globalJ];
347 auto priVarsJ = origPriVarsJ;
348
349 for (int pvIdx = 0; pvIdx < JacobianBlock::block_type::cols; ++pvIdx)
350 {
351 auto evalCouplingResidual = [&](auto priVar)
352 {
353 priVarsJ[pvIdx] = priVar;
354 this->couplingManager().updateCouplingContext(domainI, *this, domainJ, globalJ, priVarsJ, pvIdx);
355 updateCoupledVariables();
356 return this->couplingManager().evalCouplingResidual(domainI, *this, scv, domainJ, globalJ);
357 };
358
359 // derive the residuals numerically
360 ElementResidualVector partialDerivs(element.subEntities(1));
361
362 const auto& paramGroup = this->assembler().problem(domainJ).paramGroup();
363 static const int numDiffMethod = getParamFromGroup<int>(paramGroup, "Assembly.NumericDifferenceMethod");
364 static const auto epsCoupl = this->couplingManager().numericEpsilon(domainJ, paramGroup);
365
366 NumericDifferentiation::partialDerivative(evalCouplingResidual, origPriVarsJ[pvIdx], partialDerivs, origResidual,
367 epsCoupl(origPriVarsJ[pvIdx], pvIdx), numDiffMethod);
368
369 // update the global stiffness matrix with the current partial derivatives
370 for (int eqIdx = 0; eqIdx < numEq; eqIdx++)
371 {
372 // A[i][col][eqIdx][pvIdx] is the rate of change of
373 // the residual of equation 'eqIdx' at dof 'i'
374 // depending on the primary variable 'pvIdx' at dof
375 // 'col'.
376 A[scv.dofIndex()][globalJ][eqIdx][pvIdx] += partialDerivs[scv.localDofIndex()][eqIdx];
377 }
378
379 // handle Dirichlet boundary conditions
380 if (scv.boundary() && this->elemBcTypes().hasDirichlet())
381 {
382 const auto bcTypes = this->elemBcTypes()[fvGeometry.frontalScvfOnBoundary(scv).localIndex()];
383 if (bcTypes.hasDirichlet())
384 {
385 // If the dof is coupled by a Dirichlet condition,
386 // set the derived value only once (i.e. overwrite existing values).
387 // For other dofs, add the contribution of the partial derivative.
388 for (int eqIdx = 0; eqIdx < numEq; ++eqIdx)
389 {
390 for (int pvIdx = 0; pvIdx < JacobianBlock::block_type::cols; ++pvIdx)
391 {
392 if (bcTypes.isCouplingDirichlet(eqIdx))
393 A[scv.dofIndex()][globalJ][eqIdx][pvIdx] = partialDerivs[scv.localDofIndex()][pvIdx];
394 else if (bcTypes.isDirichlet(eqIdx))
395 A[scv.dofIndex()][globalJ][eqIdx][pvIdx] = 0.0;
396 }
397 }
398 }
399 }
400
401 // restore the current element solution
402 priVarsJ[pvIdx] = origPriVarsJ[pvIdx];
403
404 // restore the undeflected state of the coupling context
405 this->couplingManager().updateCouplingContext(domainI, *this, domainJ, globalJ, priVarsJ, pvIdx);
406 }
407
408 // Restore original state of the flux vars cache and/or vol vars.
409 // This has to be done in case they depend on variables of domainJ before
410 // we continue with the numeric derivative w.r.t the next globalJ. Otherwise,
411 // the next "origResidual" will be incorrect.
412 updateCoupledVariables();
413 }
414 }
415 }
416};
417
424template<std::size_t id, class TypeTag, class Assembler>
425class SubDomainFaceCenteredLocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, /*implicit=*/false>
427 id, TypeTag, Assembler,
428 SubDomainFaceCenteredLocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, false>,
429 DiffMethod::numeric, /*implicit=*/false
430>
431{
432 using ThisType = SubDomainFaceCenteredLocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, /*implicit=*/false>;
433 using ParentType = SubDomainFaceCenteredLocalAssemblerBase<id, TypeTag, Assembler, ThisType, DiffMethod::numeric, /*implicit=*/false>;
435 using FVElementGeometry = typename GridGeometry::LocalView;
436 using GridView = typename GridGeometry::GridView;
437 using Element = typename GridView::template Codim<0>::Entity;
438 using SubControlVolume = typename FVElementGeometry::SubControlVolume;
439 static constexpr auto domainI = Dune::index_constant<id>();
440public:
441 using ParentType::ParentType;
444
448 template<class ElemSol>
449 void maybeUpdateCouplingContext(const SubControlVolume& scv, ElemSol& elemSol, const int pvIdx)
450 {
451 this->couplingManager().updateCouplingContext(domainI, *this, domainI, scv.dofIndex(), elemSol[scv.localDofIndex()], pvIdx);
452 }
453
457 template<class JacobianMatrixDiagBlock, class GridVariables>
458 void maybeEvalAdditionalDomainDerivatives(const ElementResidualVector& origResiduals, const JacobianMatrixDiagBlock& A, GridVariables& gridVariables)
459 {}
460
465 template<std::size_t otherId, class JacobianBlock, class GridVariables>
466 void assembleJacobianCoupling(Dune::index_constant<otherId> domainJ, JacobianBlock& A,
467 const ElementResidualVector& res, GridVariables& gridVariables)
468 {}
469};
470
471} // end namespace Dumux
472
473#endif
The interface of the coupling manager for multi domain problems.
Definition multidomain/couplingmanager.hh:37
Definition partialreassembler.hh:32
An assembler for Jacobian and residual contribution per element (Face-centered methods).
Definition fclocalassembler.hh:328
static void partialDerivative(const Function &function, Scalar x0, FunctionEvalType &derivative, const FunctionEvalType &fx0, const int numericDifferenceMethod=1)
Computes the derivative of a function with respect to a function parameter.
Definition numericdifferentiation.hh:56
void assembleJacobianCoupling(Dune::index_constant< otherId > domainJ, JacobianBlock &A, const ElementResidualVector &res, GridVariables &gridVariables)
Computes the derivatives of residuals in subcontrolvolumes in the given element with respect to prima...
Definition subdomainfclocalassembler.hh:289
typename ParentType::LocalResidual::ElementResidualVector ElementResidualVector
export element residual vector type
Definition subdomainfclocalassembler.hh:264
void maybeUpdateCouplingContext(const SubControlVolume &scv, ElemSol &elemSol, const int pvIdx)
Update the coupling context for coupled models.
Definition subdomainfclocalassembler.hh:270
void maybeEvalAdditionalDomainDerivatives(const ElementResidualVector &origResiduals, const JacobianMatrixDiagBlock &A, GridVariables &gridVariables)
Update the additional domain derivatives for coupled models.
Definition subdomainfclocalassembler.hh:279
typename ParentType::LocalResidual::ElementResidualVector ElementResidualVector
export element residual vector type
Definition subdomainfclocalassembler.hh:443
void assembleJacobianCoupling(Dune::index_constant< otherId > domainJ, JacobianBlock &A, const ElementResidualVector &res, GridVariables &gridVariables)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition subdomainfclocalassembler.hh:466
void maybeUpdateCouplingContext(const SubControlVolume &scv, ElemSol &elemSol, const int pvIdx)
Update the coupling context for coupled models.
Definition subdomainfclocalassembler.hh:449
void maybeEvalAdditionalDomainDerivatives(const ElementResidualVector &origResiduals, const JacobianMatrixDiagBlock &A, GridVariables &gridVariables)
Update the additional domain derivatives for coupled models.
Definition subdomainfclocalassembler.hh:458
ElementResidualVector evalLocalSourceResidual(const Element &neighbor) const
Evaluates the local source term depending on time discretization scheme.
Definition subdomainfclocalassembler.hh:158
void bindLocalViews()
Prepares all local views necessary for local assembly.
Definition subdomainfclocalassembler.hh:164
const auto & curSol(Dune::index_constant< i > dId=domainId) const
Definition subdomainfclocalassembler.hh:204
const Problem & problem(Dune::index_constant< i > dId=domainId) const
return reference to the underlying problem
Definition subdomainfclocalassembler.hh:199
void assembleJacobianAndResidual(JacobianMatrixRow &jacRow, SubResidualVector &res, GridVariablesTuple &gridVariables)
Computes the derivatives with respect to the given element and adds them to the global matrix....
Definition subdomainfclocalassembler.hh:95
ElementResidualVector evalLocalSourceResidual(const Element &element, const ElementVolumeVariables &elemVolVars) const
Evaluates the local source term for an element and given element volume variables.
Definition subdomainfclocalassembler.hh:137
void assembleJacobianCoupling(Dune::index_constant< otherId > domainJ, JacRow &jacRow, const ElementResidualVector &res, GridVariables &gridVariables)
Assemble the entries in a coupling block of the jacobian. There is no coupling block between a domain...
Definition subdomainfclocalassembler.hh:119
SubDomainFaceCenteredLocalAssemblerBase(const Assembler &assembler, const Element &element, const SolutionVector &curSol, CouplingManager &couplingManager)
Definition subdomainfclocalassembler.hh:74
typename ParentType::LocalResidual::ElementResidualVector ElementResidualVector
export element residual vector type
Definition subdomainfclocalassembler.hh:71
The face-centered staggered scheme multidomain local assembler.
Definition subdomainfclocalassembler.hh:227
Defines all properties used in Dumux.
An enum class to define various differentiation methods available in order to compute the derivatives...
An assembler for Jacobian and residual contribution per element (face-centered staggered methods).
DiffMethod
Differentiation methods in order to compute the derivatives of the residual i.e. the entries in the j...
Definition diffmethod.hh:25
@ numeric
Definition diffmethod.hh:26
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition localview.hh:26
T getParamFromGroup(Args &&... args)
A free function to get a parameter from the parameter tree singleton with a model group.
Definition parameters.hh:165
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition propertysystem.hh:296
Definition adapt.hh:17
std::ranges::range auto scvs(const FVElementGeometry &fvGeometry, const LocalDof &localDof)
Definition localdof.hh:82
Definition common/pdesolver.hh:24
A class for numeric differentiation.
An adapter class for local assemblers using numeric differentiation.
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.