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;
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;
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];