From bfde81bdc3c1e31d65ca9148925c6763671a2921 Mon Sep 17 00:00:00 2001
From: Nicolas Schwenck <nicolas.schwenck@iws.uni-stuttgart.de>
Date: Wed, 29 Oct 2014 13:56:22 +0000
Subject: [PATCH] fixed wrong velocity output calculation for non-cube elements
 in decoupled models (except MPFA which anyway only works on quadrilateral
 grids)

git-svn-id: svn://svn.iws.uni-stuttgart.de/DUMUX/dumux/trunk@13584 2fb0f335-1f38-0410-981e-8018bf24f1b0
---
 .../decoupled/1p/diffusion/fv/fvvelocity1p.hh | 40 +++++++++---
 .../decoupled/2p/diffusion/fv/fvvelocity2p.hh | 62 ++++++++++++++----
 .../2p/diffusion/mimetic/mimeticpressure2p.hh | 63 +++++++++++++++----
 .../mimetic/mimeticpressure2padaptive.hh      | 63 +++++++++++++++----
 .../impes/gridadaptionindicator2plocalflux.hh | 39 +++++++++---
 5 files changed, 211 insertions(+), 56 deletions(-)

diff --git a/dumux/decoupled/1p/diffusion/fv/fvvelocity1p.hh b/dumux/decoupled/1p/diffusion/fv/fvvelocity1p.hh
index a5679dca9f..3c9aa18881 100644
--- a/dumux/decoupled/1p/diffusion/fv/fvvelocity1p.hh
+++ b/dumux/decoupled/1p/diffusion/fv/fvvelocity1p.hh
@@ -123,7 +123,15 @@ public:
 
             CellData& cellData = problem_.variables().cellData(globalIdx);
 
-            Dune::FieldVector<Scalar, 2*dim> flux(0);
+            const typename Element::Geometry& geometry = eIt->geometry();
+            // get corresponding reference element
+            typedef Dune::ReferenceElements<Scalar, dim> ReferenceElements;
+            const Dune::ReferenceElement< Scalar , dim > & refElement =
+                    ReferenceElements::general( geometry.type() );
+            const int numberOfFaces=refElement.size(1);
+
+            std::vector<Scalar> flux(numberOfFaces,0);
+
             // run through all intersections with neighbors and boundary
             IntersectionIterator
             isEndIt = problem_.gridView().iend(*eIt);
@@ -136,19 +144,31 @@ public:
                 flux[isIndex] = isIt->geometry().volume()
                         * (isIt->centerUnitOuterNormal() * cellData.fluxData().velocity(isIndex));
             }
-
             Dune::FieldVector<Scalar, dim> refVelocity(0);
-            for (int i = 0; i < dim; i++)
-                refVelocity[i] = 0.5 * (flux[2*i + 1] - flux[2*i]);
-
-            const typename Element::Geometry& geometry = eIt->geometry();
+            //2D simplices
+            if ( dim==2 && geometry.corners() == 3 ) {
+                refVelocity[0] = 1.0/3.0*(2.0*flux[1] - flux[2]);
+                refVelocity[1] = 1.0/3.0*(2.0*flux[0] - flux[2]);
+            }
+            //3D tetrahedra
+            else if ( dim==3 && geometry.corners() == 4 ){
+                DUNE_THROW(Dune::NotImplemented, "velocity output for tetrahedra not implemented");
+            }
+            //2D and 3D cubes
+            else if ( refElement.type().isCube() ){
+                for (int i = 0; i < dim; i++)
+                    refVelocity[i] = 0.5 * (flux[2*i + 1] - flux[2*i]);
+            }
+            //3D prism and pyramids
+            else {
+                DUNE_THROW(Dune::NotImplemented, "velocity output for prism/pyramid not implemented");
+            }
 
-            typedef Dune::ReferenceElements<Scalar, dim> ReferenceElements;
-            const Dune::FieldVector<Scalar, dim>& localPos 
-              = ReferenceElements::general(geometry.type()).position(0, 0);
+            const Dune::FieldVector<Scalar, dim>& localPos
+              = refElement.position(0, 0);
 
             // get the transposed Jacobian of the element mapping
-            const typename Element::Geometry::JacobianTransposed& jacobianT = 
+            const typename Element::Geometry::JacobianTransposed& jacobianT =
                 geometry.jacobianTransposed(localPos);
 
             // calculate the element velocity by the Piola transformation
diff --git a/dumux/decoupled/2p/diffusion/fv/fvvelocity2p.hh b/dumux/decoupled/2p/diffusion/fv/fvvelocity2p.hh
index d59ee2803e..d45c28026a 100644
--- a/dumux/decoupled/2p/diffusion/fv/fvvelocity2p.hh
+++ b/dumux/decoupled/2p/diffusion/fv/fvvelocity2p.hh
@@ -198,8 +198,16 @@ public:
 
                 CellData& cellData = problem_.variables().cellData(globalIdx);
 
-                Dune::FieldVector < Scalar, 2 * dim > fluxW(0);
-                Dune::FieldVector < Scalar, 2 * dim > fluxNw(0);
+                const typename Element::Geometry& geometry = eIt->geometry();
+                // get corresponding reference element
+                typedef Dune::ReferenceElements<Scalar, dim> ReferenceElements;
+                const Dune::ReferenceElement< Scalar , dim > & refElement =
+                        ReferenceElements::general( geometry.type() );
+                const int numberOfFaces=refElement.size(1);
+
+                std::vector<Scalar> fluxW(numberOfFaces,0);
+                std::vector<Scalar> fluxNw(numberOfFaces,0);
+
                 // run through all intersections with neighbors and boundary
                 IntersectionIterator isEndIt = problem_.gridView().iend(*eIt);
                 for (IntersectionIterator isIt = problem_.gridView().ibegin(*eIt); isIt != isEndIt; ++isIt)
@@ -213,31 +221,61 @@ public:
                 }
 
                 Dune::FieldVector < Scalar, dim > refVelocity(0);
-                for (int i = 0; i < dim; i++)
-                refVelocity[i] = 0.5 * (fluxW[2*i + 1] - fluxW[2*i]);
-
+                //2D simplices
+                if ( dim==2 && geometry.corners() == 3 ) {
+                    refVelocity[0] = 1.0/3.0*(2.0*fluxW[1] - fluxW[2]);
+                    refVelocity[1] = 1.0/3.0*(2.0*fluxW[0] - fluxW[2]);
+                }
+                //3D tetrahedra
+                else if ( dim==3 && geometry.corners() == 4 ){
+                    DUNE_THROW(Dune::NotImplemented, "velocity output for tetrahedra not implemented");
+                }
+                //2D and 3D cubes
+                else if ( refElement.type().isCube() ){
+                    for (int i = 0; i < dim; i++)
+                        refVelocity[i] = 0.5 * (fluxW[2*i + 1] - fluxW[2*i]);
+                }
+                //3D prism and pyramids
+                else {
+                    DUNE_THROW(Dune::NotImplemented, "velocity output for prism/pyramid not implemented");
+                }
                 const Dune::FieldVector<Scalar, dim> localPos =
-                ReferenceElements::general(eIt->geometry().type()).position(0, 0);
+                        refElement.position(0, 0);
 
                 // get the transposed Jacobian of the element mapping
                 const JacobianTransposed jacobianT =
-                    eIt->geometry().jacobianTransposed(localPos);
+                        geometry.jacobianTransposed(localPos);
 
                 // calculate the element velocity by the Piola transformation
                 Dune::FieldVector < Scalar, dim > elementVelocity(0);
                 jacobianT.umtv(refVelocity, elementVelocity);
-                elementVelocity /= eIt->geometry().integrationElement(localPos);
+                elementVelocity /= geometry.integrationElement(localPos);
 
                 velocity[globalIdx] = elementVelocity;
 
                 refVelocity = 0;
-                for (int i = 0; i < dim; i++)
-                refVelocity[i] = 0.5 * (fluxNw[2*i + 1] - fluxNw[2*i]);
-
+                //2D simplices
+                if ( dim==2 && geometry.corners() == 3 ) {
+                    refVelocity[0] = 1.0/3.0*(2.0*fluxNw[1] - fluxNw[2]);
+                    refVelocity[1] = 1.0/3.0*(2.0*fluxNw[0] - fluxNw[2]);
+                }
+                //3D tetrahedra
+                else if ( dim==3 && geometry.corners() == 4 ){
+                    DUNE_THROW(Dune::NotImplemented, "velocity output for tetrahedra not implemented");
+                }
+                //2D and 3D cubes
+                else if ( refElement.type().isCube() ){
+                    for (int i = 0; i < dim; i++)
+                        refVelocity[i] = 0.5 * (fluxNw[2*i + 1] - fluxNw[2*i]);
+                }
+                //3D prism and pyramids
+                else {
+                    DUNE_THROW(Dune::NotImplemented, "velocity output for prism/pyramid not implemented");
+                }
                 // calculate the element velocity by the Piola transformation
                 elementVelocity = 0;
                 jacobianT.umtv(refVelocity, elementVelocity);
-                elementVelocity /= eIt->geometry().integrationElement(localPos);
+                elementVelocity /= geometry.integrationElement(localPos);
 
                 velocitySecondPhase[globalIdx] = elementVelocity;
             }
diff --git a/dumux/decoupled/2p/diffusion/mimetic/mimeticpressure2p.hh b/dumux/decoupled/2p/diffusion/mimetic/mimeticpressure2p.hh
index 58badc2a04..0fe3d33964 100644
--- a/dumux/decoupled/2p/diffusion/mimetic/mimeticpressure2p.hh
+++ b/dumux/decoupled/2p/diffusion/mimetic/mimeticpressure2p.hh
@@ -280,8 +280,15 @@ public:
                     (*pressureSecond)[globalIdx] = cellData.pressure(wPhaseIdx);
                 }
 
-                Dune::FieldVector < Scalar, 2 * dim > fluxW(0);
-                Dune::FieldVector < Scalar, 2 * dim > fluxNw(0);
+                const typename Element::Geometry& geometry = eIt->geometry();
+                // get corresponding reference element
+                typedef Dune::ReferenceElements<Scalar, dim> ReferenceElements;
+                const Dune::ReferenceElement< Scalar , dim > & refElement =
+                        ReferenceElements::general( geometry.type() );
+                const int numberOfFaces=refElement.size(1);
+
+                std::vector<Scalar> fluxW(numberOfFaces,0);
+                std::vector<Scalar> fluxNw(numberOfFaces,0);
 
                 // run through all intersections with neighbors and boundary
                 IntersectionIterator isEndIt = problem_.gridView().iend(*eIt);
@@ -295,29 +302,59 @@ public:
                         * (isIt->centerUnitOuterNormal() * cellData.fluxData().velocity(nPhaseIdx, isIndex));
                 }
 
-                DimVector refVelocity;
-                for (int k = 0; k < dim; k++)
-                    refVelocity[k] = 0.5 * (fluxW[2*k+1] - fluxW[2*k]);
-                
-                const DimVector& localPos = ReferenceElements::general(eIt->geometry().type()).position(0, 0);
+                DimVector refVelocity(0.0);
+                //2D simplices
+                if ( dim==2 && geometry.corners() == 3 ) {
+                    refVelocity[0] = 1.0/3.0*(2.0*fluxW[1] - fluxW[2]);
+                    refVelocity[1] = 1.0/3.0*(2.0*fluxW[0] - fluxW[2]);
+                }
+                //3D tetrahedra
+                else if ( dim==3 && geometry.corners() == 4 ){
+                    DUNE_THROW(Dune::NotImplemented, "velocity output for tetrahedra not implemented");
+                }
+                //2D and 3D cubes
+                else if ( refElement.type().isCube() ){
+                    for (int k = 0; k < dim; k++)
+                        refVelocity[k] = 0.5 * (fluxW[2*k+1] - fluxW[2*k]);
+                }
+                //3D prism and pyramids
+                else {
+                    DUNE_THROW(Dune::NotImplemented, "velocity output for prism/pyramid not implemented");
+                }
+                const DimVector& localPos = refElement.position(0, 0);
 
                 // get the transposed Jacobian of the element mapping
-                const JacobianTransposed jacobianT = eIt->geometry().jacobianTransposed(localPos);
+                const JacobianTransposed jacobianT = geometry.jacobianTransposed(localPos);
 
                 // calculate the element velocity by the Piola transformation
                 DimVector elementVelocity(0);
                 jacobianT.umtv(refVelocity, elementVelocity);
-                elementVelocity /= eIt->geometry().integrationElement(localPos);
+                elementVelocity /= geometry.integrationElement(localPos);
 
                 (*velocityWetting)[globalIdx] = elementVelocity;
 
-                for (int k = 0; k < dim; k++)
-                    refVelocity[k] = 0.5 * (fluxNw[2*k+1] - fluxNw[2*k]);
-                
+                //2D simplices
+                if ( dim==2 && geometry.corners() == 3 ) {
+                    refVelocity[0] = 1.0/3.0*(2.0*fluxNw[1] - fluxNw[2]);
+                    refVelocity[1] = 1.0/3.0*(2.0*fluxNw[0] - fluxNw[2]);
+                }
+                //3D tetrahedra
+                else if ( dim==3 && geometry.corners() == 4 ){
+                    DUNE_THROW(Dune::NotImplemented, "velocity output for tetrahedra not implemented");
+                }
+                //2D and 3D cubes
+                else if ( refElement.type().isCube() ){
+                    for (int k = 0; k < dim; k++)
+                        refVelocity[k] = 0.5 * (fluxNw[2*k+1] - fluxNw[2*k]);
+                }
+                //3D prism and pyramids
+                else {
+                    DUNE_THROW(Dune::NotImplemented, "velocity output for prism/pyramid not implemented");
+                }
                 // calculate the element velocity by the Piola transformation
                 elementVelocity = 0;
                 jacobianT.umtv(refVelocity, elementVelocity);
-                elementVelocity /= eIt->geometry().integrationElement(localPos);
+                elementVelocity /= geometry.integrationElement(localPos);
 
                 (*velocityNonwetting)[globalIdx] = elementVelocity;
                 }
diff --git a/dumux/decoupled/2p/diffusion/mimetic/mimeticpressure2padaptive.hh b/dumux/decoupled/2p/diffusion/mimetic/mimeticpressure2padaptive.hh
index 546ea533a9..7397f651ff 100644
--- a/dumux/decoupled/2p/diffusion/mimetic/mimeticpressure2padaptive.hh
+++ b/dumux/decoupled/2p/diffusion/mimetic/mimeticpressure2padaptive.hh
@@ -292,8 +292,15 @@ public:
                     (*pressureSecond)[globalIdx] = cellData.pressure(wPhaseIdx);
                 }
 
-                Dune::FieldVector < Scalar, 2 * dim > fluxW(0);
-                Dune::FieldVector < Scalar, 2 * dim > fluxNw(0);
+                const typename Element::Geometry& geometry = eIt->geometry();
+                // get corresponding reference element
+                typedef Dune::ReferenceElements<Scalar, dim> ReferenceElements;
+                const Dune::ReferenceElement< Scalar , dim > & refElement =
+                        ReferenceElements::general( geometry.type() );
+                const int numberOfFaces=refElement.size(1);
+
+                std::vector<Scalar> fluxW(numberOfFaces,0);
+                std::vector<Scalar> fluxNw(numberOfFaces,0);
 
                 // run through all intersections with neighbors and boundary
                 IntersectionIterator isEndIt = problem_.gridView().iend(*eIt);
@@ -307,29 +314,59 @@ public:
                         * (isIt->centerUnitOuterNormal() * cellData.fluxData().velocity(nPhaseIdx, isIndex));
                 }
 
-                DimVector refVelocity;
-                for (int k = 0; k < dim; k++)
-                    refVelocity[k] = 0.5 * (fluxW[2*k+1] - fluxW[2*k]);
-
-                const DimVector& localPos = ReferenceElements::general(eIt->geometry().type()).position(0, 0);
+                Dune::FieldVector < Scalar, dim > refVelocity(0);
+                //2D simplices
+                if ( dim==2 && geometry.corners() == 3 ) {
+                    refVelocity[0] = 1.0/3.0*(2.0*fluxW[1] - fluxW[2]);
+                    refVelocity[1] = 1.0/3.0*(2.0*fluxW[0] - fluxW[2]);
+                }
+                //3D tetrahedra
+                else if ( dim==3 && geometry.corners() == 4 ){
+                    DUNE_THROW(Dune::NotImplemented, "velocity output for tetrahedra not implemented");
+                }
+                //2D and 3D cubes
+                else if ( refElement.type().isCube() ){
+                    for (int k = 0; k < dim; k++)
+                        refVelocity[k] = 0.5 * (fluxW[2*k+1] - fluxW[2*k]);
+                }
+                //3D prism and pyramids
+                else {
+                    DUNE_THROW(Dune::NotImplemented, "velocity output for prism/pyramid not implemented");
+                }
+                const DimVector& localPos = refElement.position(0, 0);
 
                 // get the transposed Jacobian of the element mapping
-                const JacobianTransposed jacobianT = eIt->geometry().jacobianTransposed(localPos);
+                const JacobianTransposed jacobianT = geometry.jacobianTransposed(localPos);
 
                 // calculate the element velocity by the Piola transformation
                 DimVector elementVelocity(0);
                 jacobianT.umtv(refVelocity, elementVelocity);
-                elementVelocity /= eIt->geometry().integrationElement(localPos);
+                elementVelocity /= geometry.integrationElement(localPos);
 
                 (*velocityWetting)[globalIdx] = elementVelocity;
 
-                for (int k = 0; k < dim; k++)
-                    refVelocity[k] = 0.5 * (fluxNw[2*k+1] - fluxNw[2*k]);
-                
+                //2D simplices
+                if ( dim==2 && geometry.corners() == 3 ) {
+                    refVelocity[0] = 1.0/3.0*(2.0*fluxNw[1] - fluxNw[2]);
+                    refVelocity[1] = 1.0/3.0*(2.0*fluxNw[0] - fluxNw[2]);
+                }
+                //3D tetrahedra
+                else if ( dim==3 && geometry.corners() == 4 ){
+                    DUNE_THROW(Dune::NotImplemented, "velocity output for tetrahedra not implemented");
+                }
+                //2D and 3D cubes
+                else if ( refElement.type().isCube() ){
+                    for (int k = 0; k < dim; k++)
+                        refVelocity[k] = 0.5 * (fluxNw[2*k+1] - fluxNw[2*k]);
+                }
+                //3D prism and pyramids
+                else {
+                    DUNE_THROW(Dune::NotImplemented, "velocity output for prism/pyramid not implemented");
+                }
                 // calculate the element velocity by the Piola transformation
                 elementVelocity = 0;
                 jacobianT.umtv(refVelocity, elementVelocity);
-                elementVelocity /= eIt->geometry().integrationElement(localPos);
+                elementVelocity /= geometry.integrationElement(localPos);
 
                 (*velocityNonwetting)[globalIdx] = elementVelocity;
                 }
diff --git a/dumux/decoupled/2p/impes/gridadaptionindicator2plocalflux.hh b/dumux/decoupled/2p/impes/gridadaptionindicator2plocalflux.hh
index ed95557630..8dc4d7cf92 100644
--- a/dumux/decoupled/2p/impes/gridadaptionindicator2plocalflux.hh
+++ b/dumux/decoupled/2p/impes/gridadaptionindicator2plocalflux.hh
@@ -211,8 +211,16 @@ public:
                 break;
             }
 
-            Dune::FieldVector < Scalar, 2 * dim > flux(0);
-            // Berechne Verfeinerungsindikator an allen Zellen
+            const typename Element::Geometry& geometry = eIt->geometry();
+            // get corresponding reference element
+            typedef Dune::ReferenceElements<Scalar, dim> ReferenceElements;
+            const Dune::ReferenceElement< Scalar , dim > & refElement =
+                    ReferenceElements::general( geometry.type() );
+            const int numberOfFaces=refElement.size(1);
+
+            std::vector<Scalar> flux(numberOfFaces,0);
+
+            // Calculate refinement indicator on all cells
             IntersectionIterator isItend = problem_.gridView().iend(*eIt);
             for (IntersectionIterator isIt = problem_.gridView().ibegin(*eIt); isIt != isItend; ++isIt)
             {
@@ -331,19 +339,34 @@ public:
             if (useFluxInd_ || usePercentileFlux_)
             {
                 DimVector refVelocity(0);
-                for (int i = 0; i < dim; i++)
-                    refVelocity[i] = 0.5 * (flux[2*i + 1] - flux[2*i]);
+                //2D simplices
+                if ( dim==2 && geometry.corners() == 3 ) {
+                    refVelocity[0] = 1.0/3.0*(2.0*flux[1] - flux[2]);
+                    refVelocity[1] = 1.0/3.0*(2.0*flux[0] - flux[2]);
+                }
+                //3D tetrahedra
+                else if ( dim==3 && geometry.corners() == 4 ){
+                    DUNE_THROW(Dune::NotImplemented, "velocity output for tetrahedra not implemented");
+                }
+                //2D and 3D cubes
+                else if ( refElement.typ().isCube() ){
+                    for (int i = 0; i < dim; i++)
+                        refVelocity[i] = 0.5 * (flux[2*i + 1] - flux[2*i]);
+                }
+                //3D prism and pyramids
+                else {
+                    DUNE_THROW(Dune::NotImplemented, "velocity output for prism/pyramid not implemented");
+                }
 
-                const DimVector& localPos =
-                    ReferenceElements::general(eIt->geometry().type()).position(0, 0);
+                const DimVector& localPos = refElement.position(0, 0);
 
                 // get the transposed Jacobian of the element mapping
-                const DimMatrix jacobianT = eIt->geometry().jacobianTransposed(localPos);
+                const DimMatrix jacobianT = geometry.jacobianTransposed(localPos);
 
                 // calculate the element velocity by the Piola transformation
                 DimVector elementVelocity(0);
                 jacobianT.umtv(refVelocity, elementVelocity);
-                elementVelocity /= eIt->geometry().integrationElement(localPos);
+                elementVelocity /= geometry.integrationElement(localPos);
 
                 Scalar velNorm = elementVelocity.two_norm();
                 indicatorVectorFlux_[globalIdxI] = std::max(velNorm, indicatorVectorFlux_[globalIdxI]);
-- 
GitLab