24#ifndef DUMUX_MULTIDOMAIN_FACET_CC_MPFA_O_LOCAL_ASSEMBLER_HH
25#define DUMUX_MULTIDOMAIN_FACET_CC_MPFA_O_LOCAL_ASSEMBLER_HH
29#include <dune/common/exceptions.hh>
30#include <dune/common/float_cmp.hh>
51template<
class P,
class EG,
class EV >
59 using Scalar =
typename IV::Traits::MatVecTraits::FaceVector::value_type;
63 using ParentType::ParentType;
78 template<
class DataHandle,
class IV,
class TensorFunc >
79 void assembleMatrices(DataHandle& handle, IV& iv,
const TensorFunc& getT, Scalar<IV> wijZeroThresh = 0.0)
81 assembleLocalMatrices_(handle.A(), handle.AB(), handle.CA(), handle.T(), handle.omegas(), iv, getT, wijZeroThresh);
84 if (iv.numUnknowns() > 0)
96 template<
class DataHandle,
class IV,
class GetU >
97 void assembleU(DataHandle& handle,
const IV& iv,
const GetU& getU)
99 auto& u = handle.uj();
103 typename IV::Traits::IndexSet::LocalIndexType i = 0;
104 for (; i < iv.numScvs(); i++)
105 u[i] = getU( this->
elemVolVars()[iv.localScv(i).gridScvIndex()] );
108 for (
const auto& data : iv.interiorBoundaryData())
110 const auto& scvf = this->
fvGeometry().scvf(data.scvfIndex());
111 const auto element = this->
fvGeometry().gridGeometry().element(scvf.insideScvIdx());
112 u[i++] = getU( this->
problem().couplingManager().getLowDimVolVars(element, scvf) );
116 for (
const auto& data : iv.dirichletData())
117 u[i++] = getU( this->
elemVolVars()[data.volVarIndex()] );
128 template<
class DataHandle,
class IV,
class GetRho >
131 using GridView =
typename IV::Traits::GridView;
132 static constexpr int dim = GridView::dimension;
133 static constexpr int dimWorld = GridView::dimensionworld;
134 static constexpr bool isSurfaceGrid = dim < dimWorld;
137 auto& g = handle.g();
138 auto& deltaG = handle.deltaG();
139 auto& outsideG = handle.gOutside();
149 using Scalar =
typename IV::Traits::MatVecTraits::TMatrix::value_type;
150 using LocalIndexType =
typename IV::Traits::IndexSet::LocalIndexType;
153 static const Scalar xi = getParamFromGroup<Scalar>(this->
problem().paramGroup(),
"FacetCoupling.Xi", 1.0);
155 for (LocalIndexType faceIdx = 0; faceIdx < iv.numFaces(); ++faceIdx)
158 const auto& curLocalScvf = iv.localScvf(faceIdx);
159 const auto& curGlobalScvf = this->
fvGeometry().scvf(curLocalScvf.gridScvfIndex());
160 const auto& gravity = this->
problem().spatialParams().gravity(curGlobalScvf.ipGlobal());
161 const auto curIsInteriorBoundary = curLocalScvf.isOnInteriorBoundary();
162 const Scalar curXiFactor = curIsInteriorBoundary ? (curGlobalScvf.boundary() ? 1.0 : xi) : 1.0;
165 const auto& neighborScvIndices = curLocalScvf.neighboringLocalScvIndices();
166 const auto& posGlobalScv = this->
fvGeometry().scv(iv.localScv(neighborScvIndices[0]).gridScvIndex());
167 const auto& posVolVars = this->
elemVolVars()[posGlobalScv];
168 const auto alpha_inside = posVolVars.extrusionFactor()*
vtmv(curGlobalScvf.unitOuterNormal(),
169 posVolVars.permeability(),
172 const auto numOutsideFaces = !curGlobalScvf.boundary() ? curGlobalScvf.numOutsideScvs() : 0;
173 using OutsideAlphaStorage = std::conditional_t< isSurfaceGrid,
175 Dune::ReservedVector<Scalar, 1> >;
176 OutsideAlphaStorage alpha_outside; alpha_outside.resize(numOutsideFaces);
177 std::fill(alpha_outside.begin(), alpha_outside.end(), 0.0);
180 if (isSurfaceGrid && !curIsInteriorBoundary)
183 if (!curLocalScvf.isDirichlet())
185 const auto localDofIdx = curLocalScvf.localDofIndex();
186 const Scalar curOneMinusXi = curIsInteriorBoundary ? -(1.0 - xi) : 1.0;
188 rho = getRho(posVolVars);
189 deltaG[localDofIdx] = 0.0;
191 if (!curGlobalScvf.boundary())
193 for (
unsigned int idxInOutside = 0; idxInOutside < curGlobalScvf.numOutsideScvs(); ++idxInOutside)
196 const auto negLocalScvIdx = neighborScvIndices[idxInOutside+1];
197 const auto& negGlobalScv = this->
fvGeometry().scv(iv.localScv(negLocalScvIdx).gridScvIndex());
198 const auto& negVolVars = this->
elemVolVars()[negGlobalScv];
199 const auto& flipScvf = !isSurfaceGrid ? curGlobalScvf
200 : this->
fvGeometry().flipScvf(curGlobalScvf.index(), idxInOutside);
202 alpha_outside[idxInOutside] = negVolVars.extrusionFactor()*
vtmv(flipScvf.unitOuterNormal(),
203 negVolVars.permeability(),
206 alpha_outside[idxInOutside] *= -1.0;
208 if (!curIsInteriorBoundary)
209 rho += getRho(negVolVars);
211 deltaG[localDofIdx] += curOneMinusXi*alpha_outside[idxInOutside];
215 if (curIsInteriorBoundary)
217 const auto posElement = this->
fvGeometry().gridGeometry().element(posGlobalScv.elementIndex());
218 const auto& facetVolVars = this->
problem().couplingManager().getLowDimVolVars(posElement, curGlobalScvf);
219 rho += getRho(facetVolVars);
221 const auto alphaFacet = posVolVars.extrusionFactor()*
vtmv(curGlobalScvf.unitOuterNormal(),
222 facetVolVars.permeability(),
224 deltaG[localDofIdx] += alphaFacet;
227 rho /= numOutsideFaces + 1;
229 deltaG[localDofIdx] -= curXiFactor*alpha_inside;
230 deltaG[localDofIdx] *= rho*curGlobalScvf.area();
233 else if (curIsInteriorBoundary)
235 const auto posElement = this->
fvGeometry().gridGeometry().element(posGlobalScv.elementIndex());
236 const auto& facetVolVars = this->
problem().couplingManager().getLowDimVolVars(posElement, curGlobalScvf);
237 rho = 0.5*(getRho(facetVolVars) + getRho(posVolVars));
241 rho = getRho(this->
elemVolVars()[curGlobalScvf.outsideScvIdx()]);
244 g[faceIdx] = alpha_inside*rho*curGlobalScvf.area();
246 if (isSurfaceGrid && !curIsInteriorBoundary)
249 for (
const auto& alpha : alpha_outside)
250 outsideG[faceIdx][i++] = alpha*rho*curGlobalScvf.area();
255 handle.CA().umv(deltaG, g);
258 using FaceVector =
typename IV::Traits::MatVecTraits::FaceVector;
261 handle.A().mv(deltaG, AG);
264 for (
const auto& localFaceData : iv.localFaceData())
267 if (!localFaceData.isOutsideFace())
270 const auto localScvIdx = localFaceData.ivLocalInsideScvIndex();
271 const auto localScvfIdx = localFaceData.ivLocalScvfIndex();
272 const auto idxInOutside = localFaceData.scvfLocalOutsideScvfIndex();
273 const auto& posLocalScv = iv.localScv(localScvIdx);
274 const auto& wijk = handle.omegas()[localScvfIdx][idxInOutside+1];
277 for (LocalIndexType localDir = 0; localDir < dim; localDir++)
280 const auto& curLocalScvf = iv.localScvf(posLocalScv.localScvfIndex(localDir));
281 if (!curLocalScvf.isDirichlet())
282 outsideG[localScvfIdx][idxInOutside] -= wijk[localDir]*AG[curLocalScvf.localDofIndex()];
292 template<
class IV,
class TensorFunc >
293 void assembleLocalMatrices_(
typename IV::Traits::MatVecTraits::AMatrix& A,
294 typename IV::Traits::MatVecTraits::BMatrix& B,
295 typename IV::Traits::MatVecTraits::CMatrix& C,
296 typename IV::Traits::MatVecTraits::DMatrix& D,
297 typename IV::Traits::MatVecTraits::OmegaStorage& wijk,
298 IV& iv,
const TensorFunc& getT,
299 Scalar<IV> wijZeroThresh)
301 using Scalar =
typename IV::Traits::MatVecTraits::TMatrix::value_type;
302 using LocalIndexType =
typename IV::Traits::IndexSet::LocalIndexType;
303 static constexpr int dim = IV::Traits::GridView::dimension;
304 static constexpr int dimWorld = IV::Traits::GridView::dimensionworld;
307 static const Scalar xi = getParamFromGroup<Scalar>(this->
problem().paramGroup(),
"FacetCoupling.Xi", 1.0);
313 if (Dune::FloatCmp::ne(xi, 1.0, 1e-6))
314 DUNE_THROW(Dune::InvalidStateException,
"Xi != 1.0 cannot be used on surface grids");
316 std::vector< std::pair<LocalIndexType, LocalIndexType> > faceMarkers;
321 if (iv.numUnknowns() == 0)
327 for (LocalIndexType faceIdx = 0; faceIdx < iv.numFaces(); ++faceIdx)
329 const auto& curLocalScvf = iv.localScvf(faceIdx);
330 const auto& curGlobalScvf = this->
fvGeometry().scvf(curLocalScvf.gridScvfIndex());
331 const auto& neighborScvIndices = curLocalScvf.neighboringLocalScvIndices();
334 const auto& posLocalScv = iv.localScv(neighborScvIndices[0]);
335 const auto& posGlobalScv = this->
fvGeometry().scv(posLocalScv.gridScvIndex());
336 const auto& posVolVars = this->
elemVolVars()[posGlobalScv];
337 const auto tensor = getT(posVolVars);
343 const auto posScvLocalDofIdx = posLocalScv.localDofIndex();
344 for (LocalIndexType localDir = 0; localDir < dim; localDir++)
346 const auto& otherLocalScvf = iv.localScvf( posLocalScv.localScvfIndex(localDir) );
347 const auto otherLocalDofIdx = otherLocalScvf.localDofIndex();
348 D[faceIdx][otherLocalDofIdx] -= wijk[faceIdx][0][localDir];
349 D[faceIdx][posScvLocalDofIdx] += wijk[faceIdx][0][localDir];
361 for (LocalIndexType faceIdx = 0; faceIdx < iv.numFaces(); ++faceIdx)
363 const auto& curLocalScvf = iv.localScvf(faceIdx);
364 const auto& curGlobalScvf = this->
fvGeometry().scvf(curLocalScvf.gridScvfIndex());
365 const auto curIsDirichlet = curLocalScvf.isDirichlet();
366 const auto curLocalDofIdx = curLocalScvf.localDofIndex();
367 const auto curIsInteriorBoundary = curLocalScvf.isOnInteriorBoundary();
368 const Scalar curXiFactor = curIsInteriorBoundary ? (curGlobalScvf.boundary() ? 1.0 : xi) : 1.0;
371 const auto& neighborScvIndices = curLocalScvf.neighboringLocalScvIndices();
372 const auto& posLocalScv = iv.localScv(neighborScvIndices[0]);
373 const auto& posGlobalScv = this->
fvGeometry().scv(posLocalScv.gridScvIndex());
374 const auto& posVolVars = this->
elemVolVars()[posGlobalScv];
375 const auto& posElement = iv.element(neighborScvIndices[0]);
376 const auto tensor = getT(posVolVars);
383 bool isZeroWij =
false;
386 for (
unsigned int localDir = 0; localDir < dim; localDir++)
388 const auto& otherLocalScvf = iv.localScvf( posLocalScv.localScvfIndex(localDir) );
389 const auto otherLocalDofIdx = otherLocalScvf.localDofIndex();
391 if (otherLocalDofIdx == curLocalDofIdx)
393 if (abs(wijk[faceIdx][0][localDir]) <= wijZeroThresh)
398 faceMarkers.emplace_back( std::make_pair(curLocalDofIdx, faceIdx) );
405 if (!otherLocalScvf.isDirichlet())
407 C[faceIdx][otherLocalDofIdx] -= wijk[faceIdx][0][localDir];
409 A[curLocalDofIdx][otherLocalDofIdx] -= curXiFactor*wijk[faceIdx][0][localDir];
414 D[faceIdx][otherLocalDofIdx] -= wijk[faceIdx][0][localDir];
416 B[curLocalDofIdx][otherLocalDofIdx] += curXiFactor*wijk[faceIdx][0][localDir];
420 const auto posScvLocalDofIdx = posLocalScv.localDofIndex();
421 D[faceIdx][posScvLocalDofIdx] += wijk[faceIdx][0][localDir];
424 B[curLocalDofIdx][posScvLocalDofIdx] -= curXiFactor*wijk[faceIdx][0][localDir];
428 if (curIsInteriorBoundary && !curIsDirichlet)
430 const auto facetVolVars = this->
problem().couplingManager().getLowDimVolVars(posElement, curGlobalScvf);
431 const auto facetTensor = getT(facetVolVars);
435 const auto wFacet = 2.0*curGlobalScvf.area()*posVolVars.extrusionFactor()
436 *
vtmv(curGlobalScvf.unitOuterNormal(), facetTensor, curGlobalScvf.unitOuterNormal())
437 / (dim < dimWorld ? sqrt(facetVolVars.extrusionFactor()) : facetVolVars.extrusionFactor());
439 A[curLocalDofIdx][curLocalDofIdx] -= wFacet;
440 B[curLocalDofIdx][curLocalScvf.coupledFacetLocalDofIndex()] -= wFacet;
443 if (!isZeroWij && abs(wFacet) <= wijZeroThresh)
446 faceMarkers.emplace_back( std::make_pair(curLocalDofIdx, faceIdx) );
451 if (!curGlobalScvf.boundary() && !curIsDirichlet)
454 const Scalar curOneMinusXi = curIsInteriorBoundary ? -(1.0 - xi) : 1.0;
457 for (
unsigned int idxInOutside = 0; idxInOutside < curGlobalScvf.numOutsideScvs(); ++idxInOutside)
459 const auto idxOnScvf = idxInOutside+1;
460 const auto& negLocalScv = iv.localScv( neighborScvIndices[idxOnScvf] );
461 const auto& negGlobalScv = this->
fvGeometry().scv(negLocalScv.gridScvIndex());
462 const auto& negVolVars = this->
elemVolVars()[negGlobalScv];
463 const auto negTensor = getT(negVolVars);
466 const auto& scvf = dim < dimWorld ? this->
fvGeometry().flipScvf(curGlobalScvf.index(), idxInOutside)
472 wijk[faceIdx][idxOnScvf] *= -1.0;
475 for (
int localDir = 0; localDir < dim; localDir++)
477 const auto otherLocalScvfIdx = negLocalScv.localScvfIndex(localDir);
478 const auto& otherLocalScvf = iv.localScvf(otherLocalScvfIdx);
479 const auto otherLocalDofIdx = otherLocalScvf.localDofIndex();
482 if (otherLocalDofIdx == curLocalDofIdx && !isZeroWij)
483 if (abs(wijk[faceIdx][idxOnScvf][localDir]) <= wijZeroThresh)
484 faceMarkers.emplace_back( std::make_pair(curLocalDofIdx, faceIdx) );
486 if (!otherLocalScvf.isDirichlet())
487 A[curLocalDofIdx][otherLocalDofIdx] += curOneMinusXi*wijk[faceIdx][idxOnScvf][localDir];
489 B[curLocalDofIdx][otherLocalDofIdx] -= curOneMinusXi*wijk[faceIdx][idxOnScvf][localDir];
492 B[curLocalDofIdx][negLocalScv.localDofIndex()] += curOneMinusXi*wijk[faceIdx][idxOnScvf][localDir];
Define some often used mathematical functions.
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
A class that contains helper functions as well as functionality which is common to different mpfa sch...
The available mpfa schemes in Dumux.
Defines the general interface of classes used for the assembly of the local systems of equations invo...
Dune::FieldVector< typename Tensor::field_type, Scv::myDimension > computeMpfaTransmissibility(const Scv &scv, const Scvf &scvf, const Tensor &T, typename Scv::ctype extrusionFactor)
Free function to evaluate the Mpfa transmissibility associated with the flux (in the form of flux = T...
Definition: mpfa/computetransmissibility.hh:51
Dune::DenseMatrix< MAT >::value_type vtmv(const Dune::DenseVector< V1 > &v1, const Dune::DenseMatrix< MAT > &M, const Dune::DenseVector< V2 > &v2)
Evaluates the scalar product of a vector v2, projected by a matrix M, with a vector v1.
Definition: math.hh:840
Defines the general interface of the local assembler classes for the assembly of the interaction volu...
Definition: localassemblerbase.hh:56
const FVElementGeometry & fvGeometry() const
Definition: localassemblerbase.hh:85
const ElementVolumeVariables & elemVolVars() const
Definition: localassemblerbase.hh:86
const Problem & problem() const
Definition: localassemblerbase.hh:84
A class that contains helper functions as well as functionality which is common to different mpfa sch...
Definition: localassemblerhelper.hh:46
static void solveLocalSystem(const FVElementGeometry &fvGeometry, DataHandle &handle, IV &iv)
Solves a previously assembled iv-local system of equations and stores the resulting transmissibilitie...
Definition: localassemblerhelper.hh:82
static void resizeMatrix(Matrix &M, size_type rows, size_type cols)
resizes a matrix to the given sizes (specialization for dynamic matrix type)
Definition: localassemblerhelper.hh:222
static void resizeVector(Vector &v, size_type size)
resizes a vector to the given size (specialization for dynamic matrix type)
Definition: localassemblerhelper.hh:238
Specialization of the interaction volume-local assembler class for the schemes using an mpfa-o type a...
Definition: multidomain/facet/cellcentered/mpfa/localassembler.hh:54
void assembleU(DataHandle &handle, const IV &iv, const GetU &getU)
Assembles the vector of primary (cell) unknowns and (maybe) Dirichlet boundary conditions within an i...
Definition: multidomain/facet/cellcentered/mpfa/localassembler.hh:97
void assembleMatrices(DataHandle &handle, IV &iv, const TensorFunc &getT, Scalar< IV > wijZeroThresh=0.0)
Assembles the matrices involved in the flux expressions and the local system of equations within an i...
Definition: multidomain/facet/cellcentered/mpfa/localassembler.hh:79
void assembleGravity(DataHandle &handle, const IV &iv, const GetRho &getRho)
Assembles the gravitational flux contributions on the scvfs within an interaction volume.
Definition: multidomain/facet/cellcentered/mpfa/localassembler.hh:129
This file contains free functions to evaluate the transmissibilities associated with flux evaluations...