123                           const Element& element,
 
  124                           const FVElementGeometry& fvGeometry,
 
  125                           const ElementVolumeVariables& elemVolVars,
 
  126                           const ElementFluxVarsCache& elemFluxVarsCache,
 
  129        const auto geometry = element.geometry();
 
  130        const Dune::GeometryType geomType = geometry.type();
 
  133        auto upwindTerm = [phaseIdx](
const auto& volVars) { 
return volVars.mobility(phaseIdx); };
 
  135        if constexpr (isBox && dim == 1)
 
  137            Velocity tmpVelocity(0.0);
 
  138            tmpVelocity = (geometry.corner(1) - geometry.corner(0));
 
  139            tmpVelocity /= tmpVelocity.two_norm();
 
  141            for (
auto&& scvf : scvfs(fvGeometry))
 
  147                FluxVariables fluxVars;
 
  148                fluxVars.init(problem_, element, fvGeometry, elemVolVars, scvf, elemFluxVarsCache);
 
  152                Scalar localArea = scvfReferenceArea_(geomType, scvf.index());
 
  153                Scalar flux = fluxVars.advectiveFlux(phaseIdx, upwindTerm) / localArea;
 
  154                const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
 
  155                flux /= insideVolVars.extrusionFactor() * Extrusion::area(fvGeometry, scvf) / scvf.area();
 
  158                const int eIdxGlobal = gridGeometry_.elementMapper().index(element);
 
  159                velocity[eIdxGlobal] = tmpVelocity;
 
  165        using Dune::referenceElement;
 
  166        const auto localPos = referenceElement(geometry).position(0, 0);
 
  167        const auto jacobianT2 = geometry.jacobianTransposed(localPos);
 
  171            using ScvVelocities = Dune::BlockVector<Velocity>;
 
  172            ScvVelocities scvVelocities(fvGeometry.numScv());
 
  175            for (
auto&& scvf : scvfs(fvGeometry))
 
  181                const auto localPosIP = geometry.local(scvf.ipGlobal());
 
  184                const auto jacobianT1 = geometry.jacobianTransposed(localPosIP);
 
  185                const auto globalNormal = scvf.unitOuterNormal();
 
  186                GlobalPosition localNormal(0);
 
  187                jacobianT1.mv(globalNormal, localNormal);
 
  188                localNormal /= localNormal.two_norm();
 
  191                FluxVariables fluxVars;
 
  192                fluxVars.init(problem_, element, fvGeometry, elemVolVars, scvf, elemFluxVarsCache);
 
  196                Scalar localArea = scvfReferenceArea_(geomType, scvf.index());
 
  197                Scalar flux = fluxVars.advectiveFlux(phaseIdx, upwindTerm) / localArea;
 
  198                const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
 
  199                flux /= insideVolVars.extrusionFactor() * Extrusion::area(fvGeometry, scvf) / scvf.area();
 
  202                Velocity tmpVelocity = localNormal;
 
  205                scvVelocities[scvf.insideScvIdx()] += tmpVelocity;
 
  206                scvVelocities[scvf.outsideScvIdx()] += tmpVelocity;
 
  210            for (
auto&& scv : scvs(fvGeometry))
 
  212                int vIdxGlobal = scv.dofIndex();
 
  215                Velocity scvVelocity(0);
 
  217                jacobianT2.mtv(scvVelocities[scv.indexInElement()], scvVelocity);
 
  218                scvVelocity /= geometry.integrationElement(localPos)*cellNum_[vIdxGlobal];
 
  220                velocity[vIdxGlobal] += scvVelocity;
 
  223        else if constexpr (isDiamond)
 
  224            DUNE_THROW(Dune::NotImplemented, 
"Velocity output with diamond discretization");
 
  231            const int numScvfsPerFace = isMpfa ? element.template subEntity<1>(0).geometry().corners() : 1;
 
  233            if (fvGeometry.numScvf() != element.subEntities(1)*numScvfsPerFace)
 
  234                DUNE_THROW(Dune::NotImplemented, 
"Velocity output for non-conforming grids");
 
  236            if (!geomType.isCube() && !geomType.isSimplex())
 
  237                DUNE_THROW(Dune::NotImplemented, 
"Velocity output for other geometry types than cube and simplex");
 
  243            std::vector<bool> handledScvf;
 
  245                handledScvf.resize(element.subEntities(1), 
false);
 
  248            std::vector<unsigned int> scvfIndexInInside(fvGeometry.numScvf());
 
  249            int localScvfIdx = 0;
 
  250            for (
const auto& intersection : intersections(gridGeometry_.gridView(), element))
 
  253                    if (handledScvf[intersection.indexInInside()])
 
  256                if (intersection.neighbor() || intersection.boundary())
 
  258                    for (
int i = 0; i < numScvfsPerFace; ++i)
 
  259                        scvfIndexInInside[localScvfIdx++] = intersection.indexInInside();
 
  263                        handledScvf[intersection.indexInInside()] = 
true;
 
  267            Dune::ReservedVector<Scalar, 2*dim> scvfFluxes(element.subEntities(1), 0.0);
 
  269            for (
auto&& scvf : scvfs(fvGeometry))
 
  271                const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
 
  272                if (!scvf.boundary())
 
  274                    FluxVariables fluxVars;
 
  275                    fluxVars.init(problem_, element, fvGeometry, elemVolVars, scvf, elemFluxVarsCache);
 
  276                    scvfFluxes[scvfIndexInInside[localScvfIdx]] += fluxVars.advectiveFlux(phaseIdx, upwindTerm)/insideVolVars.extrusionFactor();
 
  280                    auto bcTypes = problem_.boundaryTypes(element, scvf);
 
  281                    if (bcTypes.hasOnlyDirichlet())
 
  283                        FluxVariables fluxVars;
 
  284                        fluxVars.init(problem_, element, fvGeometry, elemVolVars, scvf, elemFluxVarsCache);
 
  285                        scvfFluxes[scvfIndexInInside[localScvfIdx]] += fluxVars.advectiveFlux(phaseIdx, upwindTerm)/insideVolVars.extrusionFactor();
 
  300            for (
auto&& scvf : scvfs(fvGeometry))
 
  304                    auto bcTypes = problem_.boundaryTypes(element, scvf);
 
  305                    if (bcTypes.hasNeumann())
 
  311                        if (stationaryVelocityField)
 
  313                            const auto flux = AdvectionType::flux(problem_, element, fvGeometry, elemVolVars,
 
  314                                                                  scvf, phaseIdx, elemFluxVarsCache);
 
  316                            const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
 
  317                            scvfFluxes[scvfIndexInInside[localScvfIdx]] += flux / insideVolVars.extrusionFactor();
 
  322                            const auto neumannFlux = problem_.neumann(element, fvGeometry, elemVolVars, elemFluxVarsCache, scvf);
 
  323                            using NumEqVector = std::decay_t<
decltype(neumannFlux)>;
 
  324                            if (Dune::FloatCmp::eq<NumEqVector, Dune::FloatCmp::CmpStyle::absolute>(neumannFlux, 
NumEqVector(0.0), 1e-30))
 
  325                                scvfFluxes[scvfIndexInInside[localScvfIdx]] = 0;
 
  329                            else if (dim == 1 || geomType.isCube())
 
  331                                const auto fIdx = scvfIndexInInside[localScvfIdx];
 
  333                                if constexpr (!modelIsCompositional)
 
  336                                    const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
 
  337                                    const auto eqIdx = VolumeVariables::Indices::conti0EqIdx + phaseIdx;
 
  338                                    scvfFluxes[fIdx] += neumannFlux[eqIdx] / insideVolVars.density(phaseIdx) * scvf.area();
 
  344                                    const auto fIdxOpposite = fIdx%2 ? fIdx-1 : fIdx+1;
 
  345                                    scvfFluxes[fIdx] = -scvfFluxes[fIdxOpposite];
 
  350                            else if (geomType.isSimplex())
 
  351                                scvfFluxes[scvfIndexInInside[localScvfIdx]] = 0;
 
  354                                DUNE_THROW(Dune::NotImplemented, 
"Velocity computation at Neumann boundaries for cell-centered and prism/pyramid");
 
  364            ReferenceElementVelocity refVelocity;
 
  367            if (dim == 1 || geomType.isCube())
 
  369                assert(scvfFluxes.size() == 2*dim);
 
  370                for (
int i = 0; i < dim; ++i)
 
  371                    refVelocity[i] = 0.5 * (scvfFluxes[2*i + 1] - scvfFluxes[2*i]);
 
  375            else if (geomType.isSimplex())
 
  377                assert(scvfFluxes.size() == dim+1);
 
  378                for (
int i = 0; i < dim; ++i)
 
  380                    refVelocity[i] = -scvfFluxes[dim - 1 - i];
 
  381                    for (
int fIdx = 0; fIdx < dim + 1; ++fIdx)
 
  382                        refVelocity[i] += scvfFluxes[fIdx]/(dim + 1);
 
  388                DUNE_THROW(Dune::NotImplemented, 
"Velocity computation for cell-centered and prism/pyramid");
 
  390            Velocity scvVelocity(0);
 
  391            jacobianT2.mtv(refVelocity, scvVelocity);
 
  393            scvVelocity /= geometry.integrationElement(localPos);
 
  395            int eIdxGlobal = gridGeometry_.elementMapper().index(element);
 
  397            velocity[eIdxGlobal] = scvVelocity;