version 3.11-dev
Loading...
Searching...
No Matches
assembly/cvfelocalassembler.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//
13#ifndef DUMUX_CVFE_LOCAL_ASSEMBLER_HH
14#define DUMUX_CVFE_LOCAL_ASSEMBLER_HH
15
16#include <dune/common/exceptions.hh>
17#include <dune/common/hybridutilities.hh>
18#include <dune/common/reservedvector.hh>
19#include <dune/grid/common/gridenums.hh>
20#include <dune/istl/matrixindexset.hh>
21#include <dune/istl/bvector.hh>
22
28#include <dumux/common/typetraits/localdofs_.hh>
29#include <dumux/common/typetraits/boundary_.hh>
30
36
39
40#include "cvfevolvarsdeflectionpolicy_.hh"
41
42namespace Dumux {
43
44#ifndef DOXYGEN
45namespace Detail::CVFE {
46
47struct NoOperator
48{
49 template<class... Args>
50 constexpr void operator()(Args&&...) const {}
51};
52
53template<class X, class Y>
54using Impl = std::conditional_t<!std::is_same_v<X, void>, X, Y>;
55
56} // end namespace Detail
57#endif // DOXYGEN
58
68template<class TypeTag, class Assembler, class Implementation, bool implicit>
69class CVFELocalAssemblerBase : public FVLocalAssemblerBase<TypeTag, Assembler, Implementation, implicit>
70{
75 using GridVolumeVariables = typename GridVariables::GridVolumeVariables;
76 using ElementVolumeVariables = typename GridVariables::GridVolumeVariables::LocalView;
78 using SolutionVector = typename Assembler::SolutionVector;
80 using FVElementGeometry = typename GridGeometry::LocalView;
81
82 static constexpr int numEq = GetPropType<TypeTag, Properties::ModelTraits>::numEq();
83 static constexpr int dim = GridGeometry::GridView::dimension;
84
85public:
86
87 using ParentType::ParentType;
88
90 {
92 this->elemBcTypes().update(this->asImp_().problem(), this->element(), this->fvGeometry());
93 }
94
95
100 template <class ResidualVector, class PartialReassembler = DefaultPartialReassembler, class CouplingFunction = Detail::CVFE::NoOperator>
101 void assembleJacobianAndResidual(JacobianMatrix& jac, ResidualVector& res, GridVariables& gridVariables,
102 const PartialReassembler* partialReassembler = nullptr,
103 const CouplingFunction& maybeAssembleCouplingBlocks = {})
104 {
105 this->asImp_().bindLocalViews();
106 const auto eIdxGlobal = this->asImp_().problem().gridGeometry().elementMapper().index(this->element());
107 if (partialReassembler
108 && partialReassembler->elementColor(eIdxGlobal) == EntityColor::green)
109 {
110 const auto residual = this->asImp_().evalLocalResidual(); // forward to the internal implementation
111
112 for (const auto& localDof : localDofs(this->fvGeometry()))
113 res[localDof.dofIndex()] += residual[localDof.index()];
114
115 // assemble the coupling blocks for coupled models (does nothing if not coupled)
116 maybeAssembleCouplingBlocks(residual);
117 }
118 else if (!this->elementIsGhost())
119 {
120 const auto residual = this->asImp_().assembleJacobianAndResidualImpl(jac, gridVariables, partialReassembler); // forward to the internal implementation
121
122 for (const auto& localDof : localDofs(this->fvGeometry()))
123 res[localDof.dofIndex()] += residual[localDof.index()];
124
125 // assemble the coupling blocks for coupled models (does nothing if not coupled)
126 maybeAssembleCouplingBlocks(residual);
127 }
128 else
129 {
130 // Treatment of ghost elements
131 assert(this->elementIsGhost());
132
133 // handle dofs per codimension
134 const auto& gridGeometry = this->asImp_().problem().gridGeometry();
135 Dune::Hybrid::forEach(std::make_integer_sequence<int, dim+1>{}, [&](auto d)
136 {
137 constexpr int codim = dim - d;
138 const auto& localCoeffs = gridGeometry.feCache().get(this->element().type()).localCoefficients();
139 for (int idx = 0; idx < localCoeffs.size(); ++idx)
140 {
141 const auto& localKey = localCoeffs.localKey(idx);
142
143 // skip if we are not handling this codim right now
144 if (localKey.codim() != codim)
145 continue;
146
147 // do not change the non-ghost entities
148 auto entity = this->element().template subEntity<codim>(localKey.subEntity());
149 if (entity.partitionType() == Dune::InteriorEntity || entity.partitionType() == Dune::BorderEntity)
150 continue;
151
152 // Set identity rows for ALL DOFs of this ghost entity.
153 // Entities with multiple DOFs (e.g. PQ3 edge interior DOFs with 2 per edge)
154 // require iterating over all DOF indices via asMultiMapper(dofMapper()).indices(entity).
155 using BlockType = typename JacobianMatrix::block_type;
156 for (const auto dofIndex : asMultiMapper(gridGeometry.dofMapper()).indices(entity))
157 {
158 BlockType &J = jac[dofIndex][dofIndex];
159 for (int j = 0; j < BlockType::rows; ++j)
160 J[j][j] = 1.0;
161 res[dofIndex] = 0;
162 }
163 }
164 });
165 }
166
167 auto applyDirichlet = [&] (const auto& scvOrLocalDofI,
168 const auto& dirichletValues,
169 const auto eqIdx,
170 const auto pvIdx)
171 {
172 res[scvOrLocalDofI.dofIndex()][eqIdx] = this->curElemVolVars()[scvOrLocalDofI].priVars()[pvIdx] - dirichletValues[pvIdx];
173
174 auto& row = jac[scvOrLocalDofI.dofIndex()];
175 for (auto col = row.begin(); col != row.end(); ++col)
176 row[col.index()][eqIdx] = 0.0;
177
178 jac[scvOrLocalDofI.dofIndex()][scvOrLocalDofI.dofIndex()][eqIdx][pvIdx] = 1.0;
179
180 // if a periodic dof has Dirichlet values also apply the same Dirichlet values to the other dof
181 if (this->asImp_().problem().gridGeometry().dofOnPeriodicBoundary(scvOrLocalDofI.dofIndex()))
182 {
183 const auto periodicDof = this->asImp_().problem().gridGeometry().periodicallyMappedDof(scvOrLocalDofI.dofIndex());
184 res[periodicDof][eqIdx] = this->asImp_().curSol()[periodicDof][pvIdx] - dirichletValues[pvIdx];
185
186 auto& rowP = jac[periodicDof];
187 for (auto col = rowP.begin(); col != rowP.end(); ++col)
188 rowP[col.index()][eqIdx] = 0.0;
189
190 rowP[periodicDof][eqIdx][pvIdx] = 1.0;
191 }
192 };
193
194 this->asImp_().enforceDirichletConstraints(applyDirichlet);
195 }
196
201 void assembleJacobian(JacobianMatrix& jac, GridVariables& gridVariables)
202 {
203 this->asImp_().bindLocalViews();
204 this->asImp_().assembleJacobianAndResidualImpl(jac, gridVariables); // forward to the internal implementation
205
206 auto applyDirichlet = [&] (const auto& scvOrLocalDofI,
207 const auto& dirichletValues,
208 const auto eqIdx,
209 const auto pvIdx)
210 {
211 auto& row = jac[scvOrLocalDofI.dofIndex()];
212 for (auto col = row.begin(); col != row.end(); ++col)
213 row[col.index()][eqIdx] = 0.0;
214
215 jac[scvOrLocalDofI.dofIndex()][scvOrLocalDofI.dofIndex()][eqIdx][pvIdx] = 1.0;
216 };
217
218 this->asImp_().enforceDirichletConstraints(applyDirichlet);
219 }
220
224 template <class ResidualVector>
225 void assembleResidual(ResidualVector& res)
226 {
227 this->asImp_().bindLocalViews();
228 const auto residual = this->evalLocalResidual();
229
230 for (const auto& localDof : localDofs(this->fvGeometry()))
231 res[localDof.dofIndex()] += residual[localDof.index()];
232
233 auto applyDirichlet = [&] (const auto& scvOrLocalDofI,
234 const auto& dirichletValues,
235 const auto eqIdx,
236 const auto pvIdx)
237 {
238 res[scvOrLocalDofI.dofIndex()][eqIdx] = this->curElemVolVars()[scvOrLocalDofI].priVars()[pvIdx] - dirichletValues[pvIdx];
239 };
240
241 this->asImp_().enforceDirichletConstraints(applyDirichlet);
242 }
243
245 template<typename ApplyFunction>
246 void enforceDirichletConstraints(const ApplyFunction& applyDirichlet)
247 {
248 // enforce Dirichlet boundary conditions
249 this->asImp_().evalDirichletBoundaries(applyDirichlet);
250 // take care of internal Dirichlet constraints (if enabled)
251 this->asImp_().enforceInternalDirichletConstraints(applyDirichlet);
252 }
253
257 template< typename ApplyDirichletFunctionType >
258 void evalDirichletBoundaries(ApplyDirichletFunctionType applyDirichlet)
259 {
260 // enforce Dirichlet boundaries by overwriting partial derivatives with 1 or 0
261 // and set the residual to (privar - dirichletvalue)
262 // when having the new boundary interface Dirichlet conditions are incorporated via constraints
263 if constexpr (!Detail::hasProblemBoundaryTypesForFaceFunction<Problem, FVElementGeometry>())
264 {
265 if (this->elemBcTypes().hasDirichlet())
266 {
267 for (const auto& scvI : scvs(this->fvGeometry()))
268 {
269 const auto bcTypes = this->elemBcTypes().get(this->fvGeometry(), scvI);
270 if (bcTypes.hasDirichlet())
271 {
272 const auto dirichletValues = this->asImp_().problem().dirichlet(this->element(), scvI);
273
274 // set the Dirichlet conditions in residual and jacobian
275 for (int eqIdx = 0; eqIdx < numEq; ++eqIdx)
276 {
277 if (bcTypes.isDirichlet(eqIdx))
278 {
279 const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
280 assert(0 <= pvIdx && pvIdx < numEq);
281 applyDirichlet(scvI, dirichletValues, eqIdx, pvIdx);
282 }
283 }
284 }
285 }
286 }
287 }
288 }
289
294 template<class... Args>
295 void maybeUpdateCouplingContext(Args&&...) {}
296
301 template<class... Args>
303
304};
305
315template<class TypeTag, class Assembler, DiffMethod diffMethod = DiffMethod::numeric, bool implicit = true, class Implementation = void>
317
323template<class TypeTag, class Assembler, class Implementation>
324class CVFELocalAssembler<TypeTag, Assembler, DiffMethod::numeric, /*implicit=*/true, Implementation>
325: public CVFELocalAssemblerBase<TypeTag, Assembler,
326 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::numeric, true, Implementation>>,
327 true>
328{
334 using ElementVolumeVariables = typename GridVariables::GridVolumeVariables::LocalView;
337
338 static constexpr int numEq = GetPropType<TypeTag, Properties::ModelTraits>::numEq();
340
341 static constexpr bool enableGridFluxVarsCache
342 = GridVariables::GridFluxVariablesCache::cachingEnabled;
343 static constexpr bool solutionDependentFluxVarsCache
344 = GridVariables::GridFluxVariablesCache::FluxVariablesCache::isSolDependent;
345
346public:
347
349 using ElementResidualVector = typename LocalResidual::ElementResidualVector;
350 using ParentType::ParentType;
351
358 template <class PartialReassembler = DefaultPartialReassembler>
359 ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrix& A, GridVariables& gridVariables,
360 const PartialReassembler* partialReassembler = nullptr)
361 {
362 // get some aliases for convenience
363 const auto& element = this->element();
364 const auto& fvGeometry = this->fvGeometry();
365 const auto& curSol = this->asImp_().curSol();
366
367 auto&& curElemVolVars = this->curElemVolVars();
368 auto&& elemFluxVarsCache = this->elemFluxVarsCache();
369
370 // get the vector of the actual element residuals
371 const auto origResiduals = this->evalLocalResidual();
372
374 // //
375 // Calculate derivatives of all dofs in stencil with respect to the dofs in the element. In the //
376 // neighboring elements we do so by computing the derivatives of the fluxes which depend on the //
377 // actual element. In the actual element we evaluate the derivative of the entire residual. //
378 // //
380
381 // if all volvars in the stencil have to be updated or if it's enough to only update the
382 // volVars for the scv whose associated dof has been deflected
383 static const bool updateAllVolVars = getParamFromGroup<bool>(
384 this->asImp_().problem().paramGroup(), "Assembly.BoxVolVarsDependOnAllElementDofs", false
385 );
386
387 // create the element solution
388 const auto& gridDiscretization = Deprecated::gridGeometry(fvGeometry);
389 auto elemSol = elementSolution(element, curSol, gridDiscretization);
390
391 // create the vector storing the partial derivatives
392 ElementResidualVector partialDerivs(Detail::LocalDofs::numLocalDofs(fvGeometry));
393
394 auto deflectionPolicy = Detail::CVFE::makeVariablesDeflectionPolicy(
395 gridVariables.curGridVolVars(),
398 updateAllVolVars
399 );
400
401 auto assembleDerivative = [&, this](const auto& localDof)
402 {
403 // dof index and corresponding actual pri vars
404 const auto dofIdx = localDof.dofIndex();
405 const auto localIdx = localDof.index();
406 deflectionPolicy.store(localDof);
407
408 // calculate derivatives w.r.t to the privars at the dof at hand
409 for (int pvIdx = 0; pvIdx < numEq; pvIdx++)
410 {
411 partialDerivs = 0.0;
412
413 auto evalResiduals = [&](PrimaryVariable priVar)
414 {
415 // update the volume variables and compute element residual
416 elemSol[localIdx][pvIdx] = priVar;
417 deflectionPolicy.update(elemSol, localDof, this->asImp_().problem());
418 if constexpr (solutionDependentFluxVarsCache)
419 {
421 if constexpr (enableGridFluxVarsCache)
422 gridVariables.gridFluxVarsCache().updateElement(element, fvGeometry, curElemVolVars);
423 }
424 this->asImp_().maybeUpdateCouplingContext(localDof, elemSol, pvIdx);
425 return this->evalLocalResidual();
426 };
427
428 // derive the residuals numerically
429 static const NumericEpsilon<PrimaryVariable, numEq> eps_{this->asImp_().problem().paramGroup()};
430 static const int numDiffMethod = getParamFromGroup<int>(this->asImp_().problem().paramGroup(), "Assembly.NumericDifferenceMethod");
431 NumericDifferentiation::partialDerivative(evalResiduals, elemSol[localIdx][pvIdx], partialDerivs, origResiduals,
432 eps_(elemSol[localIdx][pvIdx], pvIdx), numDiffMethod);
433
434 // update the global stiffness matrix with the current partial derivatives
435 for (const auto& localDofJ : localDofs(fvGeometry))
436 {
437 // don't add derivatives for green dofs
438 if (!partialReassembler
439 || partialReassembler->dofColor(localDofJ.dofIndex()) != EntityColor::green)
440 {
441 for (int eqIdx = 0; eqIdx < numEq; eqIdx++)
442 {
443 // A[i][col][eqIdx][pvIdx] is the rate of change of
444 // the residual of equation 'eqIdx' at dof 'i'
445 // depending on the primary variable 'pvIdx' at dof
446 // 'col'.
447 A[localDofJ.dofIndex()][dofIdx][eqIdx][pvIdx] += partialDerivs[localDofJ.index()][eqIdx];
448 }
449 }
450 }
451
452 // restore the original state of the scv's volume variables
453 deflectionPolicy.restore(localDof);
454
455 // restore the original element solution
456 elemSol[localIdx][pvIdx] = curSol[localDof.dofIndex()][pvIdx];
457 this->asImp_().maybeUpdateCouplingContext(localDof, elemSol, pvIdx);
458 }
459 };
460
461 // calculation of the derivatives
462 for (const auto& localDof : localDofs(fvGeometry))
463 assembleDerivative(localDof);
464
465 // restore original state of the flux vars cache in case of global caching.
466 // In the case of local caching this is obsolete because the elemFluxVarsCache used here goes out of scope after this.
467 if constexpr (enableGridFluxVarsCache)
468 gridVariables.gridFluxVarsCache().updateElement(element, fvGeometry, curElemVolVars);
469
470 // evaluate additional derivatives that might arise from the coupling (no-op if not coupled)
471 this->asImp_().maybeEvalAdditionalDomainDerivatives(origResiduals, A, gridVariables);
472
473 return origResiduals;
474 }
475
476}; // implicit CVFEAssembler with numeric Jacobian
477
483template<class TypeTag, class Assembler, class Implementation>
484class CVFELocalAssembler<TypeTag, Assembler, DiffMethod::numeric, /*implicit=*/false, Implementation>
485: public CVFELocalAssemblerBase<TypeTag, Assembler,
486 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::numeric, false, Implementation>>,
487 false>
488{
495
496 static constexpr int numEq = GetPropType<TypeTag, Properties::ModelTraits>::numEq();
498
499public:
500
502 using ElementResidualVector = typename LocalResidual::ElementResidualVector;
503 using ParentType::ParentType;
504
511 template <class PartialReassembler = DefaultPartialReassembler>
512 ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrix& A, GridVariables& gridVariables,
513 const PartialReassembler* partialReassembler = nullptr)
514 {
515 if (partialReassembler)
516 DUNE_THROW(Dune::NotImplemented, "partial reassembly for explicit time discretization");
517
518 // get some aliases for convenience
519 const auto& element = this->element();
520 const auto& fvGeometry = this->fvGeometry();
521 const auto& curSol = this->asImp_().curSol();
522 auto&& curElemVolVars = this->curElemVolVars();
523
524 // get the vecor of the actual element residuals
525 const auto origResiduals = this->evalLocalResidual();
526 const auto origStorageResiduals = this->evalLocalStorageResidual();
527
529 // //
530 // Calculate derivatives of all dofs in stencil with respect to the dofs in the element. In the //
531 // neighboring elements we do so by computing the derivatives of the fluxes which depend on the //
532 // actual element. In the actual element we evaluate the derivative of the entire residual. //
533 // //
535
536 // create the element solution
537 const auto& gridDiscretization = Deprecated::gridGeometry(fvGeometry);
538 auto elemSol = elementSolution(element, curSol, gridDiscretization);
539
540 // create the vector storing the partial derivatives
541 ElementResidualVector partialDerivs(Detail::LocalDofs::numLocalDofs(fvGeometry));
542
543 // calculation of the derivatives
544 for (const auto& scv : scvs(fvGeometry))
545 {
546 // dof index and corresponding actual pri vars
547 const auto localIdx = scv.localDofIndex();
548 const auto dofIdx = scv.dofIndex();
549 auto& curVolVars = this->getVolVarAccess(gridVariables.curGridVolVars(), curElemVolVars, scv);
550 const VolumeVariables origVolVars(curVolVars);
551
552 // calculate derivatives w.r.t to the privars at the dof at hand
553 for (int pvIdx = 0; pvIdx < numEq; pvIdx++)
554 {
555 partialDerivs = 0.0;
556
557 auto evalStorage = [&](Scalar priVar)
558 {
559 // auto partialDerivsTmp = partialDerivs;
560 elemSol[localIdx][pvIdx] = priVar;
561 curVolVars.update(elemSol, this->asImp_().problem(), element, scv);
562 return this->evalLocalStorageResidual();
563 };
564
565 // derive the residuals numerically
566 static const NumericEpsilon<Scalar, numEq> eps_{this->asImp_().problem().paramGroup()};
567 static const int numDiffMethod = getParamFromGroup<int>(this->asImp_().problem().paramGroup(), "Assembly.NumericDifferenceMethod");
568 NumericDifferentiation::partialDerivative(evalStorage, elemSol[localIdx][pvIdx], partialDerivs, origStorageResiduals,
569 eps_(elemSol[localIdx][pvIdx], pvIdx), numDiffMethod);
570
571 // update the global stiffness matrix with the current partial derivatives
572 for (int eqIdx = 0; eqIdx < numEq; eqIdx++)
573 {
574 // A[i][col][eqIdx][pvIdx] is the rate of change of
575 // the residual of equation 'eqIdx' at dof 'i'
576 // depending on the primary variable 'pvIdx' at dof
577 // 'col'.
578 A[dofIdx][dofIdx][eqIdx][pvIdx] += partialDerivs[localIdx][eqIdx];
579 }
580
581 // restore the original state of the scv's volume variables
582 curVolVars = origVolVars;
583
584 // restore the original element solution
585 elemSol[localIdx][pvIdx] = curSol[dofIdx][pvIdx];
586 // TODO additional dof dependencies
587 }
588 }
589
590 return origResiduals;
591 }
592}; // explicit CVFEAssembler with numeric Jacobian
593
599template<class TypeTag, class Assembler, class Implementation>
600class CVFELocalAssembler<TypeTag, Assembler, DiffMethod::analytic, /*implicit=*/true, Implementation>
601: public CVFELocalAssemblerBase<TypeTag, Assembler,
602 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::analytic, true, Implementation>>,
603 true>
604{
609
610public:
611
613 using ElementResidualVector = typename LocalResidual::ElementResidualVector;
614 using ParentType::ParentType;
615
622 template <class PartialReassembler = DefaultPartialReassembler>
623 ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrix& A, GridVariables& gridVariables,
624 const PartialReassembler* partialReassembler = nullptr)
625 {
626 if (partialReassembler)
627 DUNE_THROW(Dune::NotImplemented, "partial reassembly for analytic differentiation");
628
629 // get some aliases for convenience
630 const auto& element = this->element();
631 const auto& fvGeometry = this->fvGeometry();
632 const auto& problem = this->asImp_().problem();
633 const auto& curElemVolVars = this->curElemVolVars();
634 const auto& elemFluxVarsCache = this->elemFluxVarsCache();
635
636 // get the vecor of the actual element residuals
637 const auto origResiduals = this->evalLocalResidual();
638
640 // //
641 // Calculate derivatives of all dofs in stencil with respect to the dofs in the element. In the //
642 // neighboring elements we do so by computing the derivatives of the fluxes which depend on the //
643 // actual element. In the actual element we evaluate the derivative of the entire residual. //
644 // //
646
647 // calculation of the source and storage derivatives
648 for (const auto& scv : scvs(fvGeometry))
649 {
650 // dof index and corresponding actual pri vars
651 const auto dofIdx = scv.dofIndex();
652 const auto& volVars = curElemVolVars[scv];
653
654 // derivative of this scv residual w.r.t the d.o.f. of the same scv (because of mass lumping)
655 // only if the problem is instationary we add derivative of storage term
656 // TODO if e.g. porosity depends on all dofs in the element, we would have off-diagonal matrix entries!?
657 if (!this->assembler().isStationaryProblem())
658 this->localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
659 problem,
660 element,
662 volVars,
663 scv);
664
665 // derivative of this scv residual w.r.t the d.o.f. of the same scv (because of mass lumping)
666 // add source term derivatives
667 this->localResidual().addSourceDerivatives(A[dofIdx][dofIdx],
668 problem,
669 element,
671 volVars,
672 scv);
673 }
674
675 // localJacobian[scvIdx][otherScvIdx][eqIdx][priVarIdx] of the fluxes
676 for (const auto& scvf : scvfs(fvGeometry))
677 {
678 if (!scvf.boundary())
679 {
680 // add flux term derivatives
681 this->localResidual().addFluxDerivatives(A,
682 problem,
683 element,
687 scvf);
688 }
689
690 // the boundary gets special treatment to simplify
691 // for the user
692 else
693 {
694 const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx());
695 if (this->elemBcTypes().get(fvGeometry, insideScv).hasNeumann())
696 {
697 // add flux term derivatives
698 this->localResidual().addRobinFluxDerivatives(A[insideScv.dofIndex()],
699 problem,
700 element,
704 scvf);
705 }
706 }
707 }
708
709 return origResiduals;
710 }
711
712}; // implicit CVFEAssembler with analytic Jacobian
713
719template<class TypeTag, class Assembler, class Implementation>
720class CVFELocalAssembler<TypeTag, Assembler, DiffMethod::analytic, /*implicit=*/false, Implementation>
721: public CVFELocalAssemblerBase<TypeTag, Assembler,
722 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::analytic, false, Implementation>>,
723 false>
724{
729
730public:
731
733 using ElementResidualVector = typename LocalResidual::ElementResidualVector;
734 using ParentType::ParentType;
735
742 template <class PartialReassembler = DefaultPartialReassembler>
743 ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrix& A, GridVariables& gridVariables,
744 const PartialReassembler* partialReassembler = nullptr)
745 {
746 if (partialReassembler)
747 DUNE_THROW(Dune::NotImplemented, "partial reassembly for explicit time discretization");
748
749 // get some aliases for convenience
750 const auto& element = this->element();
751 const auto& fvGeometry = this->fvGeometry();
752 const auto& problem = this->asImp_().problem();
753 const auto& curElemVolVars = this->curElemVolVars();
754
755 // get the vecor of the actual element residuals
756 const auto origResiduals = this->evalLocalResidual();
757
759 // //
760 // Calculate derivatives of all dofs in stencil with respect to the dofs in the element. In the //
761 // neighboring elements we do so by computing the derivatives of the fluxes which depend on the //
762 // actual element. In the actual element we evaluate the derivative of the entire residual. //
763 // //
765
766 // calculation of the source and storage derivatives
767 for (const auto& scv : scvs(fvGeometry))
768 {
769 // dof index and corresponding actual pri vars
770 const auto dofIdx = scv.dofIndex();
771 const auto& volVars = curElemVolVars[scv];
772
773 // derivative of this scv residual w.r.t the d.o.f. of the same scv (because of mass lumping)
774 // only if the problem is instationary we add derivative of storage term
775 this->localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
776 problem,
777 element,
779 volVars,
780 scv);
781 }
782
783 return origResiduals;
784 }
785
786}; // explicit CVFEAssembler with analytic Jacobian
787
788} // end namespace Dumux
789
790#endif
A base class for all local assemblers.
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition assembly/cvfelocalassembler.hh:733
ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrix &A, GridVariables &gridVariables, const PartialReassembler *partialReassembler=nullptr)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition assembly/cvfelocalassembler.hh:743
typename ParentType::LocalResidual LocalResidual
Definition assembly/cvfelocalassembler.hh:732
ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrix &A, GridVariables &gridVariables, const PartialReassembler *partialReassembler=nullptr)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition assembly/cvfelocalassembler.hh:623
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition assembly/cvfelocalassembler.hh:613
typename ParentType::LocalResidual LocalResidual
Definition assembly/cvfelocalassembler.hh:612
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition assembly/cvfelocalassembler.hh:349
typename ParentType::LocalResidual LocalResidual
Definition assembly/cvfelocalassembler.hh:348
ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrix &A, GridVariables &gridVariables, const PartialReassembler *partialReassembler=nullptr)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition assembly/cvfelocalassembler.hh:359
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition assembly/cvfelocalassembler.hh:502
ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrix &A, GridVariables &gridVariables, const PartialReassembler *partialReassembler=nullptr)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition assembly/cvfelocalassembler.hh:512
typename ParentType::LocalResidual LocalResidual
Definition assembly/cvfelocalassembler.hh:501
A base class for all local CVFE assemblers.
Definition assembly/cvfelocalassembler.hh:70
void enforceDirichletConstraints(const ApplyFunction &applyDirichlet)
Enforce Dirichlet constraints.
Definition assembly/cvfelocalassembler.hh:246
void assembleResidual(ResidualVector &res)
Assemble the residual only.
Definition assembly/cvfelocalassembler.hh:225
void maybeUpdateCouplingContext(Args &&...)
Update the coupling context for coupled models.
Definition assembly/cvfelocalassembler.hh:295
void assembleJacobian(JacobianMatrix &jac, GridVariables &gridVariables)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition assembly/cvfelocalassembler.hh:201
void evalDirichletBoundaries(ApplyDirichletFunctionType applyDirichlet)
Evaluates Dirichlet boundaries.
Definition assembly/cvfelocalassembler.hh:258
void assembleJacobianAndResidual(JacobianMatrix &jac, ResidualVector &res, GridVariables &gridVariables, const PartialReassembler *partialReassembler=nullptr, const CouplingFunction &maybeAssembleCouplingBlocks={})
Computes the derivatives with respect to the given element and adds them to the global matrix....
Definition assembly/cvfelocalassembler.hh:101
void bindLocalViews()
Definition assembly/cvfelocalassembler.hh:89
void maybeEvalAdditionalDomainDerivatives(Args &&...)
Update the additional domain derivatives for coupled models.
Definition assembly/cvfelocalassembler.hh:302
An assembler for Jacobian and residual contribution per element (CVFE methods).
Definition assembly/cvfelocalassembler.hh:316
void bindLocalViews()
Definition assembly/fvlocalassemblerbase.hh:173
ElementVolumeVariables & curElemVolVars()
Definition assembly/fvlocalassemblerbase.hh:253
ElementBoundaryTypes & elemBcTypes()
Definition assembly/fvlocalassemblerbase.hh:269
Implementation & asImp_()
Definition assembly/fvlocalassemblerbase.hh:297
ElementResidualVector evalLocalResidual() const
Definition assembly/fvlocalassemblerbase.hh:108
const Problem & problem() const
Definition assembly/fvlocalassemblerbase.hh:229
FVLocalAssemblerBase(const Assembler &assembler, const Element &element, const SolutionVector &curSol)
Definition assembly/fvlocalassemblerbase.hh:61
FVElementGeometry & fvGeometry()
Definition assembly/fvlocalassemblerbase.hh:249
bool elementIsGhost() const
Definition assembly/fvlocalassemblerbase.hh:241
std::decay_t< decltype(std::declval< Assembler >().localResidual())> LocalResidual
Definition assembly/fvlocalassemblerbase.hh:55
const Element & element() const
Definition assembly/fvlocalassemblerbase.hh:237
VolumeVariables & getVolVarAccess(GridVolumeVariables &gridVolVars, ElementVolumeVariables &elemVolVars, const SubControlVolume &scv)
Definition assembly/fvlocalassemblerbase.hh:304
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:50
A helper class for local assemblers using numeric differentiation to determine the epsilon.
Definition numericepsilon.hh:32
detects which entries in the Jacobian have to be recomputed
Definition partialreassembler.hh:420
Defines all properties used in Dumux.
The local element solution class for control-volume finite element methods.
Helpers for deprecation.
An enum class to define various differentiation methods available in order to compute the derivatives...
An enum class to define the colors of elements and vertices required for partial Jacobian reassembly.
DiffMethod
Differentiation methods in order to compute the derivatives of the residual i.e. the entries in the j...
Definition diffmethod.hh:25
@ analytic
Definition diffmethod.hh:26
@ numeric
Definition diffmethod.hh:26
@ green
does not need to be reassembled
Definition entitycolor.hh:40
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
T getParamFromGroup(Args &&... args)
A free function to get a parameter from the parameter tree singleton with a model group.
Definition parameters.hh:149
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.
Adapter to expose a multi-DOF mapper interface for single- and multi-DOF mappers.
Definition cvfe/elementvariables.hh:25
Definition adapt.hh:17
constexpr auto asMultiMapper(const Mapper &mapper)
Definition multimapperview.hh:48
std::ranges::range auto scvs(const FVElementGeometry &fvGeometry, const LocalDof &localDof)
Definition localdof.hh:82
auto localDofs(const FVElementGeometry &fvGeometry)
range over local dofs
Definition localdof.hh:50
A class for numeric differentiation.
An adapter class for local assemblers using numeric differentiation.
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
Detects which entries in the Jacobian have to be recomputed.