173 const auto& element = this->element();
174 const auto& fvGeometry = this->fvGeometry();
175 const auto& gridGeometry = this->assembler().gridGeometry();
176 auto&& curElemVolVars = this->curElemVolVars();
177 auto&& elemFluxVarsCache = this->elemFluxVarsCache();
180 const auto globalI = gridGeometry.elementMapper().index(element);
181 const auto& connectivityMap = gridGeometry.connectivityMap();
182 const auto numNeighbors = connectivityMap[globalI].size();
185 Dune::ReservedVector<Element, maxElementStencilSize> neighborElements;
186 neighborElements.resize(numNeighbors);
190 Residuals origResiduals(numNeighbors + 1); origResiduals = 0.0;
191 origResiduals[0] = this->evalLocalResidual()[0];
196 auto evalNeighborFlux = [&] (
const auto& neighbor,
const auto& scvf)
198 if (neighbor.partitionType() == Dune::GhostEntity)
201 return this->localResidual().evalFlux(this->problem(),
204 this->curElemVolVars(),
205 this->elemFluxVarsCache(), scvf);
211 for (
const auto& dataJ : connectivityMap[globalI])
213 neighborElements[j-1] = gridGeometry.element(dataJ.globalJ);
214 for (
const auto scvfIdx : dataJ.scvfsJ)
215 origResiduals[j] += evalNeighborFlux(neighborElements[j-1], fvGeometry.scvf(scvfIdx));
221 const auto& scv = fvGeometry.scv(globalI);
222 auto& curVolVars = ParentType::getVolVarAccess(gridVariables.curGridVolVars(), curElemVolVars, scv);
226 const auto& curSol = this->curSol();
227 const auto origPriVars = curSol[globalI];
228 const auto origVolVars = curVolVars;
235 Residuals partialDerivs(numNeighbors + 1);
237 for (
int pvIdx = 0; pvIdx < numEq; ++pvIdx)
241 auto evalResiduals = [&](Scalar priVar)
243 Residuals partialDerivsTmp(numNeighbors + 1);
244 partialDerivsTmp = 0.0;
246 elemSol[0][pvIdx] = priVar;
247 curVolVars.update(elemSol, this->problem(), element, scv);
248 elemFluxVarsCache.update(element, fvGeometry, curElemVolVars);
249 if (enableGridFluxVarsCache)
250 gridVariables.gridFluxVarsCache().updateElement(element, fvGeometry, curElemVolVars);
253 partialDerivsTmp[0] = this->evalLocalResidual()[0];
256 for (std::size_t k = 0; k < numNeighbors; ++k)
257 for (
auto scvfIdx : connectivityMap[globalI][k].scvfsJ)
258 partialDerivsTmp[k+1] += evalNeighborFlux(neighborElements[k], fvGeometry.scvf(scvfIdx));
260 return partialDerivsTmp;
265 static const int numDiffMethod = getParamFromGroup<int>(this->problem().paramGroup(),
"Assembly.NumericDifferenceMethod");
267 eps_(elemSol[0][pvIdx], pvIdx), numDiffMethod);
272 if (this->elementIsGhost())
274 partialDerivs[0] = 0.0;
275 partialDerivs[0][pvIdx] = 1.0;
279 curVolVars = origVolVars;
282 elemSol[0][pvIdx] = origPriVars[pvIdx];
286 if constexpr (Problem::enableInternalDirichletConstraints())
289 const auto internalDirichletConstraintsOwnElement = this->problem().hasInternalDirichletConstraint(this->element(), scv);
290 const auto dirichletValues = this->problem().internalDirichlet(this->element(), scv);
292 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx)
294 if (internalDirichletConstraintsOwnElement[eqIdx])
296 origResiduals[0][eqIdx] = origVolVars.priVars()[eqIdx] - dirichletValues[eqIdx];
297 A[globalI][globalI][eqIdx][pvIdx] = (eqIdx == pvIdx) ? 1.0 : 0.0;
300 A[globalI][globalI][eqIdx][pvIdx] += partialDerivs[0][eqIdx];
305 for (
const auto& dataJ : connectivityMap[globalI])
307 const auto& neighborElement = neighborElements[j-1];
308 const auto& neighborScv = fvGeometry.scv(dataJ.globalJ);
309 const auto internalDirichletConstraintsNeighbor = this->problem().hasInternalDirichletConstraint(neighborElement, neighborScv);
311 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx)
313 if (internalDirichletConstraintsNeighbor[eqIdx])
314 A[dataJ.globalJ][globalI][eqIdx][pvIdx] = 0.0;
316 A[dataJ.globalJ][globalI][eqIdx][pvIdx] += partialDerivs[j][eqIdx];
324 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
327 A[globalI][globalI][eqIdx][pvIdx] += partialDerivs[0][eqIdx];
331 for (
const auto& dataJ : connectivityMap[globalI])
332 A[dataJ.globalJ][globalI][eqIdx][pvIdx] += partialDerivs[j++][eqIdx];
343 if (enableGridFluxVarsCache)
344 gridVariables.gridFluxVarsCache().updateElement(element, fvGeometry, curElemVolVars);
347 return origResiduals[0];