From 6ebe40d8e2d4cc773452c1404a4c7d6d7a2fcc2d Mon Sep 17 00:00:00 2001
From: Martin Schneider <martin.schneider@iws.uni-stuttgart.de>
Date: Fri, 21 Jun 2024 13:12:09 +0200
Subject: [PATCH] [fix][flux] Fix tpfa transmissibility for dispersion flux

---
 dumux/flux/cctpfa/dispersionflux.hh | 60 +++++++++++++++++++++++++++--
 1 file changed, 56 insertions(+), 4 deletions(-)

diff --git a/dumux/flux/cctpfa/dispersionflux.hh b/dumux/flux/cctpfa/dispersionflux.hh
index 185b6f323f..0916f16992 100644
--- a/dumux/flux/cctpfa/dispersionflux.hh
+++ b/dumux/flux/cctpfa/dispersionflux.hh
@@ -111,12 +111,15 @@ public:
                 ModelTraits::CompositionalDispersionModel::compositionalDispersionTensor(problem, scvf, fvGeometry,
                                                                                          elemVolVars, elemFluxVarsCache,
                                                                                          phaseIdx, compIdx);
-            const auto dij = computeTpfaTransmissibility(fvGeometry, scvf, fvGeometry.scv(scvf.insideScvIdx()), dispersionTensor, insideVolVars.extrusionFactor());
+
+            // Here we assume that the Dispersion tensor is given at the scvfs such that Di = Dj
+            // This means that we don't have to distinguish between inside and outside tensors
+            const auto tij = calculateTransmissibility_(fvGeometry, elemVolVars, scvf, dispersionTensor);
 
             const auto xInside = massOrMoleFraction(insideVolVars, referenceSystem, phaseIdx, compIdx);
             const auto xOutide = massOrMoleFraction(outsideVolVars, referenceSystem, phaseIdx, compIdx);
 
-            componentFlux[compIdx] = (rho * (xInside-xOutide) * dij) * scvf.area();
+            componentFlux[compIdx] = (rho * tij * (xInside-xOutide));
         }
         return componentFlux;
     }
@@ -145,14 +148,63 @@ public:
             ModelTraits::ThermalDispersionModel::thermalDispersionTensor(problem, scvf, fvGeometry,
                                                                          elemVolVars, elemFluxVarsCache,
                                                                          phaseIdx);
-        const auto dij = computeTpfaTransmissibility(scvf, fvGeometry.scv(scvf.insideScvIdx()), dispersionTensor, insideVolVars.extrusionFactor());
+
+        // Here we assume that the Dispersion tensor is given at the scvfs such that Di = Dj
+        // This means that we don't have to distinguish between inside and outside tensors
+        const auto tij = calculateTransmissibility_(fvGeometry, elemVolVars, scvf, dispersionTensor);
 
         // get the inside/outside temperatures
         const auto tInside = insideVolVars.temperature();
         const auto tOutside = outsideVolVars.temperature();
 
         // compute the heat conduction flux
-        return (tInside-tOutside) * dij * scvf.area();
+        return tij * (tInside-tOutside);
+    }
+
+private:
+
+    //! Compute transmissibilities
+    template<class Tensor>
+    static Scalar calculateTransmissibility_(const FVElementGeometry& fvGeometry,
+                                             const ElementVolumeVariables& elemVolVars,
+                                             const SubControlVolumeFace& scvf,
+                                             const Tensor& D)
+    {
+        Scalar tij;
+
+        const auto insideScvIdx = scvf.insideScvIdx();
+        const auto& insideScv = fvGeometry.scv(insideScvIdx);
+        const auto& insideVolVars = elemVolVars[insideScvIdx];
+
+        const Scalar ti = computeTpfaTransmissibility(fvGeometry, scvf, insideScv, D, insideVolVars.extrusionFactor());
+
+        // for the boundary (dirichlet) we only need ti
+        if (scvf.boundary())
+        {
+            tij = Extrusion::area(fvGeometry, scvf)*ti;
+        }
+        // otherwise we compute a tpfa harmonic mean
+        else
+        {
+            const auto outsideScvIdx = scvf.outsideScvIdx();
+            const auto& outsideScv = fvGeometry.scv(outsideScvIdx);
+            const auto& outsideVolVars = elemVolVars[outsideScvIdx];
+
+            Scalar tj;
+            if constexpr (dim == dimWorld)
+                // assume the normal vector from outside is anti parallel so we save flipping a vector
+                tj = -1.0*computeTpfaTransmissibility(fvGeometry, scvf, outsideScv, D, outsideVolVars.extrusionFactor());
+            else
+                tj = computeTpfaTransmissibility(fvGeometry, fvGeometry.flipScvf(scvf.index()), outsideScv, D, outsideVolVars.extrusionFactor());
+
+            // check for division by zero!
+            if (ti*tj <= 0.0)
+                tij = 0;
+            else
+                tij = Extrusion::area(fvGeometry, scvf)*(ti * tj)/(ti + tj);
+        }
+
+        return tij;
     }
 
 };
-- 
GitLab