101 const Element& element,
102 const FVElementGeometry& fvGeometry,
103 const ElementVolumeVariables& elemVolVars,
104 const ElementFluxVarsCache& elemFluxVarsCache,
107 using Velocity =
typename VelocityVector::value_type;
109 const auto geometry = element.geometry();
110 const Dune::GeometryType geomType = geometry.type();
113 auto upwindTerm = [phaseIdx](
const auto& volVars) {
return volVars.mobility(phaseIdx); };
115 if(isBox && dim == 1)
117 Velocity tmpVelocity(0.0);
118 tmpVelocity = (geometry.corner(1) - geometry.corner(0));
119 tmpVelocity /= tmpVelocity.two_norm();
121 for (
auto&& scvf : scvfs(fvGeometry))
127 FluxVariables fluxVars;
128 fluxVars.init(problem_, element, fvGeometry, elemVolVars, scvf, elemFluxVarsCache);
132 Scalar localArea = scvfReferenceArea_(geomType, scvf.index());
133 Scalar flux = fluxVars.advectiveFlux(phaseIdx, upwindTerm) / localArea;
134 const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
135 flux /= insideVolVars.extrusionFactor();
138 const int eIdxGlobal = gridGeometry_.elementMapper().index(element);
139 velocity[eIdxGlobal] = tmpVelocity;
145 const auto referenceElement = ReferenceElements::general(geomType);
146 const auto& localPos = referenceElement.position(0, 0);
147 const auto jacobianT2 = geometry.jacobianTransposed(localPos);
151 using ScvVelocities = Dune::BlockVector<Velocity>;
152 ScvVelocities scvVelocities(fvGeometry.numScv());
155 for (
auto&& scvf : scvfs(fvGeometry))
161 const auto localPosIP = geometry.local(scvf.ipGlobal());
164 const auto jacobianT1 = geometry.jacobianTransposed(localPosIP);
165 const auto globalNormal = scvf.unitOuterNormal();
166 GlobalPosition localNormal(0);
167 jacobianT1.mv(globalNormal, localNormal);
168 localNormal /= localNormal.two_norm();
171 FluxVariables fluxVars;
172 fluxVars.init(problem_, element, fvGeometry, elemVolVars, scvf, elemFluxVarsCache);
176 Scalar localArea = scvfReferenceArea_(geomType, scvf.index());
177 Scalar flux = fluxVars.advectiveFlux(phaseIdx, upwindTerm) / localArea;
178 const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
179 flux /= insideVolVars.extrusionFactor();
182 Velocity tmpVelocity = localNormal;
185 scvVelocities[scvf.insideScvIdx()] += tmpVelocity;
186 scvVelocities[scvf.outsideScvIdx()] += tmpVelocity;
190 for (
auto&& scv : scvs(fvGeometry))
192 int vIdxGlobal = scv.dofIndex();
195 Velocity scvVelocity(0);
197 jacobianT2.mtv(scvVelocities[scv.indexInElement()], scvVelocity);
198 scvVelocity /= geometry.integrationElement(localPos)*cellNum_[vIdxGlobal];
200 velocity[vIdxGlobal] += scvVelocity;
209 const int numScvfsPerFace = isMpfa ? element.template subEntity<1>(0).geometry().corners() : 1;
211 if (fvGeometry.numScvf() != element.subEntities(1)*numScvfsPerFace)
212 DUNE_THROW(Dune::NotImplemented,
"Velocity output for non-conforming grids");
214 if (!geomType.isCube() && !geomType.isSimplex())
215 DUNE_THROW(Dune::NotImplemented,
"Velocity output for other geometry types than cube and simplex");
221 std::vector<bool> handledScvf;
223 handledScvf.resize(element.subEntities(1),
false);
226 std::vector<unsigned int> scvfIndexInInside(fvGeometry.numScvf());
227 int localScvfIdx = 0;
228 for (
const auto& intersection :
intersections(gridGeometry_.gridView(), element))
231 if (handledScvf[intersection.indexInInside()])
234 if (intersection.neighbor() || intersection.boundary())
236 for (
int i = 0; i < numScvfsPerFace; ++i)
237 scvfIndexInInside[localScvfIdx++] = intersection.indexInInside();
241 handledScvf[intersection.indexInInside()] =
true;
245 std::vector<Scalar> scvfFluxes(element.subEntities(1), 0.0);
247 for (
auto&& scvf : scvfs(fvGeometry))
249 const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
250 if (!scvf.boundary())
252 FluxVariables fluxVars;
253 fluxVars.init(problem_, element, fvGeometry, elemVolVars, scvf, elemFluxVarsCache);
254 scvfFluxes[scvfIndexInInside[localScvfIdx]] += fluxVars.advectiveFlux(phaseIdx, upwindTerm)/insideVolVars.extrusionFactor();
258 auto bcTypes = problemBoundaryTypes_(element, scvf);
259 if (bcTypes.hasOnlyDirichlet())
261 FluxVariables fluxVars;
262 fluxVars.init(problem_, element, fvGeometry, elemVolVars, scvf, elemFluxVarsCache);
263 scvfFluxes[scvfIndexInInside[localScvfIdx]] += fluxVars.advectiveFlux(phaseIdx, upwindTerm)/insideVolVars.extrusionFactor();
278 for (
auto&& scvf : scvfs(fvGeometry))
282 auto bcTypes = problemBoundaryTypes_(element, scvf);
283 if (bcTypes.hasNeumann())
286 const auto neumannFlux = Deprecated::neumann(problem_, element, fvGeometry, elemVolVars, elemFluxVarsCache, scvf);
287 using NumEqVector = std::decay_t<
decltype(neumannFlux)>;
288 if (Dune::FloatCmp::eq<NumEqVector, Dune::FloatCmp::CmpStyle::absolute>(neumannFlux, NumEqVector(0.0), 1e-30))
289 scvfFluxes[scvfIndexInInside[localScvfIdx]] = 0;
291 else if (dim == 1 || geomType.isCube())
293 const auto fIdx = scvfIndexInInside[localScvfIdx];
294 const auto fIdxOpposite = fIdx%2 ? fIdx-1 : fIdx+1;
295 scvfFluxes[fIdx] = -scvfFluxes[fIdxOpposite];
298 else if (geomType.isSimplex())
299 scvfFluxes[scvfIndexInInside[localScvfIdx]] = 0;
307 Velocity refVelocity;
310 if (dim == 1 || geomType.isCube())
312 for (
int i = 0; i < dim; i++)
313 refVelocity[i] = 0.5 * (scvfFluxes[2*i + 1] - scvfFluxes[2*i]);
316 else if (geomType.isSimplex())
318 for (
int dimIdx = 0; dimIdx < dim; dimIdx++)
320 refVelocity[dimIdx] = -scvfFluxes[dim - 1 - dimIdx];
321 for (
int fIdx = 0; fIdx < dim + 1; fIdx++)
322 refVelocity[dimIdx] += scvfFluxes[fIdx]/(dim + 1);
327 DUNE_THROW(Dune::NotImplemented,
"velocity output for cell-centered and prism/pyramid");
329 Velocity scvVelocity(0);
330 jacobianT2.mtv(refVelocity, scvVelocity);
332 scvVelocity /= geometry.integrationElement(localPos);
334 int eIdxGlobal = gridGeometry_.elementMapper().index(element);
336 velocity[eIdxGlobal] = scvVelocity;