version 3.11-dev
Loading...
Searching...
No Matches
multidomain/subdomaincvfelocalassembler.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_SUBDOMAIN_CVFE_LOCAL_ASSEMBLER_HH
15#define DUMUX_MULTIDOMAIN_SUBDOMAIN_CVFE_LOCAL_ASSEMBLER_HH
16
17#include <type_traits>
18
19#include <dune/common/reservedvector.hh>
20#include <dune/common/indices.hh>
21#include <dune/common/hybridutilities.hh>
22#include <dune/grid/common/gridenums.hh> // for GhostEntity
23#include <dune/istl/matrixindexset.hh>
24
25#include <dumux/common/typetraits/localdofs_.hh>
26#include <dumux/common/typetraits/boundary_.hh>
37
38namespace Dumux {
39
51template<std::size_t id, class TypeTag, class Assembler, class Implementation, DiffMethod dm, bool implicit>
52class SubDomainCVFELocalAssemblerBase : public CVFELocalAssembler<TypeTag, Assembler, dm, implicit, Implementation>
53{
55
59 using SolutionVector = typename Assembler::SolutionVector;
61
63 using GridVolumeVariables = typename GridVariables::GridVolumeVariables;
64 using ElementVolumeVariables = typename GridVolumeVariables::LocalView;
65 using ElementFluxVariablesCache = typename GridVariables::GridFluxVariablesCache::LocalView;
66 using Scalar = typename GridVariables::Scalar;
67
68 using GridGeometry = typename GridVariables::GridGeometry;
69 using FVElementGeometry = typename GridGeometry::LocalView;
70 using Extrusion = Extrusion_t<GridGeometry>;
71 using GridView = typename GridGeometry::GridView;
72 using Element = typename GridView::template Codim<0>::Entity;
73
74 using CouplingManager = typename Assembler::CouplingManager;
75
76 static constexpr auto numEq = GetPropType<TypeTag, Properties::ModelTraits>::numEq();
77
78public:
80 static constexpr auto domainId = typename Dune::index_constant<id>();
82 using ParentType::ParentType;
84 using ElementResidualVector = typename ParentType::LocalResidual::ElementResidualVector;
85
86 // the constructor
88 const Assembler& assembler,
89 const Element& element,
90 const SolutionVector& curSol,
91 CouplingManager& couplingManager
92 )
93 : ParentType(assembler,
94 element,
95 curSol,
96 localView(assembler.gridGeometry(domainId)),
97 localView(assembler.gridVariables(domainId).curGridVolVars()),
98 localView(assembler.gridVariables(domainId).prevGridVolVars()),
99 localView(assembler.gridVariables(domainId).gridFluxVarsCache()),
100 assembler.localResidual(domainId),
101 (element.partitionType() == Dune::GhostEntity))
102 , couplingManager_(couplingManager)
103 {}
104
109 template<class JacobianMatrixRow, class SubResidualVector, class GridVariablesTuple>
110 void assembleJacobianAndResidual(JacobianMatrixRow& jacRow, SubResidualVector& res, GridVariablesTuple& gridVariables)
111 {
112 auto assembleCouplingBlocks = [&](const auto& residual)
113 {
114 // assemble the coupling blocks
115 using namespace Dune::Hybrid;
116 forEach(integralRange(Dune::Hybrid::size(jacRow)), [&](auto&& i)
117 {
118 if constexpr (std::decay_t<decltype(i)>{} != id)
119 this->assembleJacobianCoupling(i, jacRow, residual, gridVariables);
120 });
121 };
122
123 // the coupled model does not support partial reassembly yet
124 const DefaultPartialReassembler* noReassembler = nullptr;
125 ParentType::assembleJacobianAndResidual(jacRow[domainId], res, *std::get<domainId>(gridVariables), noReassembler, assembleCouplingBlocks);
126 }
127
132 template<std::size_t otherId, class JacRow, class GridVariables,
133 typename std::enable_if_t<(otherId == id), int> = 0>
134 void assembleJacobianCoupling(Dune::index_constant<otherId> domainJ, JacRow& jacRow,
135 const ElementResidualVector& res, GridVariables& gridVariables)
136 {}
137
141 template<std::size_t otherId, class JacRow, class GridVariables,
142 typename std::enable_if_t<(otherId != id), int> = 0>
143 void assembleJacobianCoupling(Dune::index_constant<otherId> domainJ, JacRow& jacRow,
144 const ElementResidualVector& res, GridVariables& gridVariables)
145 {
146 this->asImp_().assembleJacobianCoupling(domainJ, jacRow[domainJ], res, *std::get<domainId>(gridVariables));
147 }
148
152 ElementResidualVector evalLocalSourceResidual(const Element& element, const ElementVolumeVariables& elemVolVars) const
153 {
154 static_assert(!Detail::LocalDofs::hasNonCVLocalDofsInterface<FVElementGeometry>(), "Separate source calculation not implemented for hybrid schemes.");
155
156 // initialize the residual vector for all scvs in this element
157 ElementResidualVector residual(Detail::LocalDofs::numLocalDofs(this->fvGeometry()));
158
159 // evaluate the source term
160 // forward to the local residual specialized for the discretization methods
161 for (const auto& scv : scvs(this->fvGeometry()))
162 {
163 const auto& curVolVars = elemVolVars[scv];
164 auto source = this->localResidual().computeSource(problem(), element, this->fvGeometry(), elemVolVars, scv);
165 source *= -Extrusion::volume(this->fvGeometry(), scv)*curVolVars.extrusionFactor();
166 residual[scv.localDofIndex()] = std::move(source);
167 }
168
169 return residual;
170 }
171
175 ElementResidualVector evalLocalSourceResidual(const Element& neighbor) const
176 { return this->evalLocalSourceResidual(neighbor, implicit ? this->curElemVolVars() : this->prevElemVolVars()); }
177
182 {
183 // get some references for convenience
184 const auto& element = this->element();
185 const auto& curSol = this->curSol(domainId);
186 auto&& fvGeometry = this->fvGeometry();
187 auto&& curElemVolVars = this->curElemVolVars();
188 auto&& elemFluxVarsCache = this->elemFluxVarsCache();
189
190 // bind the caches
191 couplingManager_.bindCouplingContext(domainId, element, this->assembler());
192 fvGeometry.bind(element);
193
194 if constexpr (implicit)
195 {
196 curElemVolVars.bind(element, fvGeometry, curSol);
197 elemFluxVarsCache.bind(element, fvGeometry, curElemVolVars);
198 if (!this->assembler().isStationaryProblem())
199 this->prevElemVolVars().bindElement(element, fvGeometry, this->assembler().prevSol()[domainId]);
200 }
201 else
202 {
203 auto& prevElemVolVars = this->prevElemVolVars();
204 const auto& prevSol = this->assembler().prevSol()[domainId];
205
206 curElemVolVars.bindElement(element, fvGeometry, curSol);
207 prevElemVolVars.bind(element, fvGeometry, prevSol);
208 elemFluxVarsCache.bind(element, fvGeometry, prevElemVolVars);
209 }
210
211 this->elemBcTypes().update(problem(), this->element(), this->fvGeometry());
212 }
213
215 template<std::size_t i = domainId>
216 const Problem& problem(Dune::index_constant<i> dId = domainId) const
217 { return this->assembler().problem(domainId); }
218
220 template<std::size_t i = domainId>
221 const auto& curSol(Dune::index_constant<i> dId = domainId) const
222 { return ParentType::curSol()[dId]; }
223
225 CouplingManager& couplingManager()
226 { return couplingManager_; }
227
228private:
229 CouplingManager& couplingManager_;
230};
231
243template<std::size_t id, class TypeTag, class Assembler, DiffMethod DM = DiffMethod::numeric, bool implicit = true>
245
252template<std::size_t id, class TypeTag, class Assembler>
253class SubDomainCVFELocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, /*implicit=*/true>
254: public SubDomainCVFELocalAssemblerBase<id, TypeTag, Assembler,
256{
257 using ThisType = SubDomainCVFELocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, /*implicit=*/true>;
258 using ParentType = SubDomainCVFELocalAssemblerBase<id, TypeTag, Assembler, ThisType, DiffMethod::numeric, /*implicit=*/true>;
259
261 using GridView = typename GridGeometry::GridView;
262 using FVElementGeometry = typename GridGeometry::LocalView;
263 using Element = typename GridView::template Codim<0>::Entity;
265
266 static constexpr int numEq = GetPropType<TypeTag, Properties::ModelTraits>::numEq();
267 static constexpr int dim = GridView::dimension;
268
271 static constexpr auto domainI = Dune::index_constant<id>();
272
273public:
274 using ParentType::ParentType;
277
281 template<class ScvOrLocalDof, class ElemSol>
282 void maybeUpdateCouplingContext(const ScvOrLocalDof& scvOrLocalDof, ElemSol& elemSol, const int pvIdx)
283 {
284 this->couplingManager().updateCouplingContext(domainI, *this, domainI, scvOrLocalDof.dofIndex(), elemSol[Detail::LocalDofs::index(scvOrLocalDof)], pvIdx);
285 }
286
290 template<class JacobianMatrixDiagBlock, class GridVariables>
291 void maybeEvalAdditionalDomainDerivatives(const ElementResidualVector& origResiduals, JacobianMatrixDiagBlock& A, GridVariables& gridVariables)
292 {
293 this->couplingManager().evalAdditionalDomainDerivatives(domainI, *this, origResiduals, A, gridVariables);
294 }
295
300 template<std::size_t otherId, class JacobianBlock, class GridVariables>
301 void assembleJacobianCoupling(Dune::index_constant<otherId> domainJ, JacobianBlock& A,
302 const ElementResidualVector& res, GridVariables& gridVariables)
303 {
305 // Calculate derivatives of all dofs in the element with respect to all dofs in the coupling stencil. //
307
308 // get some aliases for convenience
309 const auto& element = this->element();
310 const auto& fvGeometry = this->fvGeometry();
311 auto&& curElemVolVars = this->curElemVolVars();
312 auto&& elemFluxVarsCache = this->elemFluxVarsCache();
313
314 // convenience lambda for call to update self
315 auto updateCoupledVariables = [&] ()
316 {
317 // Update ourself after the context has been modified. Depending on the
318 // type of caching, other objects might have to be updated. All ifs can be optimized away.
319 if constexpr (enableGridFluxVarsCache)
320 {
321 if constexpr (enableGridVolVarsCache)
322 this->couplingManager().updateCoupledVariables(domainI, *this, gridVariables.curGridVolVars(), gridVariables.gridFluxVarsCache());
323 else
324 this->couplingManager().updateCoupledVariables(domainI, *this, curElemVolVars, gridVariables.gridFluxVarsCache());
325 }
326 else
327 {
328 if constexpr (enableGridVolVarsCache)
329 this->couplingManager().updateCoupledVariables(domainI, *this, gridVariables.curGridVolVars(), elemFluxVarsCache);
330 else
331 this->couplingManager().updateCoupledVariables(domainI, *this, curElemVolVars, elemFluxVarsCache);
332 }
333 };
334
335 // get element stencil information
336 const auto& stencil = this->couplingManager().couplingStencil(domainI, element, domainJ);
337 const auto& curSolJ = this->curSol(domainJ);
338 for (const auto globalJ : stencil)
339 {
340 // undeflected privars and privars to be deflected
341 const auto origPriVarsJ = curSolJ[globalJ];
342 auto priVarsJ = origPriVarsJ;
343
344 // the undeflected coupling residual
345 const auto origResidual = this->couplingManager().evalCouplingResidual(domainI, *this, domainJ, globalJ);
346
347 for (int pvIdx = 0; pvIdx < JacobianBlock::block_type::cols; ++pvIdx)
348 {
349 auto evalCouplingResidual = [&](auto priVar)
350 {
351 priVarsJ[pvIdx] = priVar;
352 this->couplingManager().updateCouplingContext(domainI, *this, domainJ, globalJ, priVarsJ, pvIdx);
353 updateCoupledVariables();
354 return this->couplingManager().evalCouplingResidual(domainI, *this, domainJ, globalJ);
355 };
356
357 // derive the residuals numerically
358 ElementResidualVector partialDerivs(Detail::LocalDofs::numLocalDofs(fvGeometry));
359
360 const auto& paramGroup = this->assembler().problem(domainJ).paramGroup();
361 static const int numDiffMethod = getParamFromGroup<int>(paramGroup, "Assembly.NumericDifferenceMethod");
362 static const auto epsCoupl = this->couplingManager().numericEpsilon(domainJ, paramGroup);
363
364 NumericDifferentiation::partialDerivative(evalCouplingResidual, origPriVarsJ[pvIdx], partialDerivs, origResidual,
365 epsCoupl(origPriVarsJ[pvIdx], pvIdx), numDiffMethod);
366
367 // update the global stiffness matrix with the current partial derivatives
368 for (const auto& scv : scvs(fvGeometry))
369 {
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 // For the old boundary interface we set them for each scv
379 // for the new interface we enforce them globally by constraints, i.e. do nothing here
380 if constexpr (!Detail::hasProblemBoundaryTypesForFaceFunction<Problem, FVElementGeometry>())
381 {
382 // If the dof is coupled by a Dirichlet condition,
383 // set the derived value only once (i.e. overwrite existing values).
384 if (this->elemBcTypes().hasDirichlet())
385 {
386 const auto bcTypes = this->elemBcTypes().get(fvGeometry, scv);
387 if (bcTypes.isCouplingDirichlet(eqIdx))
388 A[scv.dofIndex()][globalJ][eqIdx][pvIdx] = partialDerivs[scv.localDofIndex()][eqIdx];
389 else if (bcTypes.isDirichlet(eqIdx))
390 A[scv.dofIndex()][globalJ][eqIdx][pvIdx] = 0.0;
391 }
392 }
393
394 // enforce internal Dirichlet constraints
395 if constexpr (Problem::enableInternalDirichletConstraints())
396 {
397 const auto internalDirichletConstraints = this->problem().hasInternalDirichletConstraint(this->element(), scv);
398 if (internalDirichletConstraints[eqIdx])
399 A[scv.dofIndex()][globalJ][eqIdx][pvIdx] = 0.0;
400 }
401 }
402 }
403
404 // update the global stiffness matrix with the current partial derivatives for non-cv dofs
405 if constexpr (Detail::LocalDofs::hasNonCVLocalDofsInterface<FVElementGeometry>())
406 {
407 for (const auto& localDof : nonCVLocalDofs(fvGeometry))
408 {
409 for (int eqIdx = 0; eqIdx < numEq; eqIdx++)
410 {
411 // A[i][col][eqIdx][pvIdx] is the rate of change of
412 // the residual of equation 'eqIdx' at dof 'i'
413 // depending on the primary variable 'pvIdx' at dof
414 // 'col'.
415 A[localDof.dofIndex()][globalJ][eqIdx][pvIdx] += partialDerivs[localDof.index()][eqIdx];
416 }
417 }
418 }
419
420 // restore the current element solution
421 priVarsJ[pvIdx] = origPriVarsJ[pvIdx];
422
423 // restore the undeflected state of the coupling context
424 this->couplingManager().updateCouplingContext(domainI, *this, domainJ, globalJ, priVarsJ, pvIdx);
425 }
426
427 // Restore original state of the flux vars cache and/or vol vars.
428 // This has to be done in case they depend on variables of domainJ before
429 // we continue with the numeric derivative w.r.t the next globalJ. Otherwise,
430 // the next "origResidual" will be incorrect.
431 updateCoupledVariables();
432 }
433 }
434};
435
442template<std::size_t id, class TypeTag, class Assembler>
443class SubDomainCVFELocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, /*implicit=*/false>
444: public SubDomainCVFELocalAssemblerBase<id, TypeTag, Assembler,
445 SubDomainCVFELocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, false>, DiffMethod::numeric, false >
446{
447 using ThisType = SubDomainCVFELocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, /*implicit=*/false>;
448 using ParentType = SubDomainCVFELocalAssemblerBase<id, TypeTag, Assembler, ThisType, DiffMethod::numeric, /*implicit=*/false>;
449
450public:
451 using ParentType::ParentType;
454
461 template<std::size_t otherId, class JacobianBlock, class GridVariables>
462 void assembleJacobianCoupling(Dune::index_constant<otherId> domainJ, JacobianBlock& A,
463 const ElementResidualVector& res, GridVariables& gridVariables)
464 {}
465};
466
467} // end namespace Dumux
468
469#endif
An assembler for Jacobian and residual contribution per element (CVFE methods).
An assembler for Jacobian and residual contribution per element (CVFE methods).
Definition assembly/cvfelocalassembler.hh:335
The interface of the coupling manager for multi domain problems.
Definition multidomain/couplingmanager.hh:37
Definition partialreassembler.hh:32
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
typename ParentType::LocalResidual::ElementResidualVector ElementResidualVector
export element residual vector type
Definition multidomain/subdomaincvfelocalassembler.hh:453
void assembleJacobianCoupling(Dune::index_constant< otherId > domainJ, JacobianBlock &A, const ElementResidualVector &res, GridVariables &gridVariables)
Computes the coupling derivatives with respect to the given element and adds them to the global matri...
Definition multidomain/subdomaincvfelocalassembler.hh:462
void maybeEvalAdditionalDomainDerivatives(const ElementResidualVector &origResiduals, JacobianMatrixDiagBlock &A, GridVariables &gridVariables)
Update the additional domain derivatives for coupled models.
Definition multidomain/subdomaincvfelocalassembler.hh:291
typename ParentType::LocalResidual::ElementResidualVector ElementResidualVector
export element residual vector type
Definition multidomain/subdomaincvfelocalassembler.hh:276
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 multidomain/subdomaincvfelocalassembler.hh:301
void maybeUpdateCouplingContext(const ScvOrLocalDof &scvOrLocalDof, ElemSol &elemSol, const int pvIdx)
Update the coupling context for coupled models.
Definition multidomain/subdomaincvfelocalassembler.hh:282
const auto & curSol(Dune::index_constant< i > dId=domainId) const
Definition multidomain/subdomaincvfelocalassembler.hh:221
static constexpr auto domainId
Definition multidomain/subdomaincvfelocalassembler.hh:80
SubDomainCVFELocalAssemblerBase(const Assembler &assembler, const Element &element, const SolutionVector &curSol, CouplingManager &couplingManager)
Definition multidomain/subdomaincvfelocalassembler.hh:87
ElementResidualVector evalLocalSourceResidual(const Element &element, const ElementVolumeVariables &elemVolVars) const
Evaluates the local source term for an element and given element volume variables.
Definition multidomain/subdomaincvfelocalassembler.hh:152
void bindLocalViews()
Prepares all local views necessary for local assembly.
Definition multidomain/subdomaincvfelocalassembler.hh:181
typename ParentType::LocalResidual::ElementResidualVector ElementResidualVector
export element residual vector type
Definition multidomain/subdomaincvfelocalassembler.hh:84
ElementResidualVector evalLocalSourceResidual(const Element &neighbor) const
Evaluates the local source term depending on time discretization scheme.
Definition multidomain/subdomaincvfelocalassembler.hh:175
const Problem & problem(Dune::index_constant< i > dId=domainId) const
return reference to the underlying problem
Definition multidomain/subdomaincvfelocalassembler.hh:216
CouplingManager & couplingManager()
Definition multidomain/subdomaincvfelocalassembler.hh:225
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 multidomain/subdomaincvfelocalassembler.hh:134
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 multidomain/subdomaincvfelocalassembler.hh:110
The CVFE scheme multidomain local assembler.
Definition multidomain/subdomaincvfelocalassembler.hh:244
Defines all properties used in Dumux.
An enum class to define various differentiation methods available in order to compute the derivatives...
Helper classes to compute the integration elements.
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
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
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
Class representing dofs on elements for control-volume finite element schemes.
Definition adapt.hh:17
std::ranges::range auto scvs(const FVElementGeometry &fvGeometry, const LocalDof &localDof)
Definition localdof.hh:82
typename Extrusion< T >::type Extrusion_t
Convenience alias for obtaining the extrusion type.
Definition extrusion.hh:257
Definition common/pdesolver.hh:24
A helper to deduce a vector with the same size as numbers of equations.
A class for numeric differentiation.
An adapter class for local assemblers using numeric differentiation.
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
A arithmetic block vector type based on DUNE's reserved vector.