From f4f0e599231ca03d8d5f1b286c5404d80e382745 Mon Sep 17 00:00:00 2001
From: Robert K <robertk@posteo.org>
Date: Mon, 5 Sep 2022 15:30:43 +0200
Subject: [PATCH] [feature][fluxes] Added HLL for potential temperature
 formulation.

---
 dune/fem-dg/models/defaultmodel.hh            |  10 ++
 dune/fem-dg/models/modelwrapper.hh            |  28 ++++-
 dune/fem-dg/operator/dg/dgpyoperator.hh       |   1 +
 .../operator/fluxes/advection/parameters.hh   |   6 +-
 .../operator/fluxes/euler/eulerflux_impl.hh   | 110 ++++++++++--------
 dune/fem-dg/operator/fluxes/euler/fluxes.hh   |  19 +++
 python/dune/femdg/patch.py                    |  10 ++
 7 files changed, 130 insertions(+), 54 deletions(-)

diff --git a/dune/fem-dg/models/defaultmodel.hh b/dune/fem-dg/models/defaultmodel.hh
index ec7de0f6..eb7c38bf 100644
--- a/dune/fem-dg/models/defaultmodel.hh
+++ b/dune/fem-dg/models/defaultmodel.hh
@@ -218,6 +218,16 @@ namespace Fem
       globalMax = -1e308;
     }
 
+    /**
+     *  \brief compute pressure and temperature for compressible flow
+     */
+    template <class State>
+    void pressureTemperatur( const State& u, double& p, double& T ) const
+    {
+      p = 0.0;
+      T = 0.0;
+    }
+
     /**
      * \brief returns the mass factor term \f$ R \f$
      *
diff --git a/dune/fem-dg/models/modelwrapper.hh b/dune/fem-dg/models/modelwrapper.hh
index 81293776..8a6cc25c 100644
--- a/dune/fem-dg/models/modelwrapper.hh
+++ b/dune/fem-dg/models/modelwrapper.hh
@@ -226,9 +226,9 @@ namespace Fem
     template <class Entity>
     void setEntity( const Entity& entity ) const
     {
-      if( hasAdvection )
+      if constexpr ( hasAdvection )
         advection().init( entity );
-      if( hasDiffusion )
+      if constexpr ( hasDiffusion )
         diffusion().init( entity );
     }
 
@@ -249,6 +249,28 @@ namespace Fem
       return (min - max).infinity_norm() < 1e-10;
     }
 
+    template <class State> // double[dim+2]
+    void pressureTemperature( const State& u, double& p, double& T ) const
+    {
+      if constexpr ( hasAdvection )
+      {
+        const auto pT = advection().pressureTemperature( u );
+        p = pT[0];
+        T = pT[1];
+        return ;
+      }
+
+      if constexpr ( hasDiffusion )
+      {
+        const auto pT = diffusion().pressureTemperature( u );
+        p = pT[0];
+        T = pT[1];
+        return ;
+      }
+
+      p = 0.0;
+      T = 0.0;
+    }
 
     template <class LocalEvaluation>
     inline double stiffSource( const LocalEvaluation& local,
@@ -288,7 +310,7 @@ namespace Fem
                             const RangeType& u,
                             RangeType& maxValue) const
     {
-      if( hasDiffusion )
+      if constexpr ( hasDiffusion )
       {
         maxValue = diffusion().diffusionTimeStep( local.entity(), local.quadraturePoint(), u );
       }
diff --git a/dune/fem-dg/operator/dg/dgpyoperator.hh b/dune/fem-dg/operator/dg/dgpyoperator.hh
index 6b3aaf9e..5b465ab4 100644
--- a/dune/fem-dg/operator/dg/dgpyoperator.hh
+++ b/dune/fem-dg/operator/dg/dgpyoperator.hh
@@ -18,6 +18,7 @@
 // dune-fem-dg includes
 #include <dune/fem-dg/algorithm/evolution.hh>
 #include <dune/fem-dg/operator/fluxes/advection/fluxes.hh>
+#include <dune/fem-dg/operator/fluxes/euler/fluxes.hh>
 #include <dune/fem-dg/operator/dg/operatortraits.hh>
 #include <dune/fem-dg/operator/dg/primaloperator.hh>
 #include <dune/fem-dg/models/modelwrapper.hh>
diff --git a/dune/fem-dg/operator/fluxes/advection/parameters.hh b/dune/fem-dg/operator/fluxes/advection/parameters.hh
index c839bf0c..de4313d5 100644
--- a/dune/fem-dg/operator/fluxes/advection/parameters.hh
+++ b/dune/fem-dg/operator/fluxes/advection/parameters.hh
@@ -38,6 +38,8 @@ namespace Fem
       euler_llf,
       //! the Harten, Lax and van Leer (HLL) flux
       euler_hll,
+      //! the Harten, Lax and van Leer (HLL) flux with potential temperature formulation
+      euler_hll_pt,
       //! the HLLC flux
       euler_hllc,
       //! general flux: Parameter selection is done via parameter file!
@@ -55,12 +57,12 @@ namespace Fem
 
     //! Contains all known enums for advection fluxes which can be chosen via parameter file.
     const Enum        _enums[] = { Enum::none, Enum::upwind, Enum::llf,
-                                   Enum::euler_llf, Enum::euler_hll, Enum::euler_hllc,
+                                   Enum::euler_llf, Enum::euler_hll, Enum::euler_hll_pt, Enum::euler_hllc,
                                    Enum::mhd_dw, Enum::mhd_hllem
                                    };
     //! Contains all known names of advection fluxes which can be chosen via parameter file.
     const std::string _strings[] = { "NONE", "UPWIND" , "LLF",
-                                     "EULER-LLF", "EULER-HLL" , "EULER-HLLC",
+                                     "EULER-LLF", "EULER-HLL" , "EULER-HLL-PT", "EULER-HLLC",
                                      "MHD-DW", "MHD-HLLEM"
                                      };
     //! Number of known advection fluxes which can be chosen via parameter file.
diff --git a/dune/fem-dg/operator/fluxes/euler/eulerflux_impl.hh b/dune/fem-dg/operator/fluxes/euler/eulerflux_impl.hh
index eea74349..4524100a 100644
--- a/dune/fem-dg/operator/fluxes/euler/eulerflux_impl.hh
+++ b/dune/fem-dg/operator/fluxes/euler/eulerflux_impl.hh
@@ -24,7 +24,7 @@ namespace EulerNumFlux
   //
   ////////////////////////////////////////////////////////
 
-  typedef enum {LLF, HLL, HLLC} EulerFluxType;
+  typedef enum {LLF, HLL, HLL_PT, HLLC} EulerFluxType;
   const EulerFluxType std_flux_type = HLL;
 
   /**
@@ -74,11 +74,14 @@ namespace EulerNumFlux
     FieldType num_flux(const FieldType Uj[dim+2], const FieldType Un[dim+2],
                        const FieldType normal[dim], FieldType gj[dim+2]) const
     {
-      if (flux_type == LLF) return num_flux_LLF(Uj, Un, normal, gj);
+      if constexpr (flux_type == LLF) return num_flux_LLF(Uj, Un, normal, gj);
 
-      if (flux_type == HLL) return num_flux_HLL(Uj, Un, normal, gj);
+      if constexpr (flux_type == HLL) return num_flux_HLL(Uj, Un, normal, gj, std::false_type());
 
-      if (flux_type == HLLC) return num_flux_HLLC(Uj, Un, normal, gj);
+      // potential temperature
+      if constexpr (flux_type == HLL_PT) return num_flux_HLL(Uj, Un, normal, gj, std::true_type());
+
+      if constexpr (flux_type == HLLC) return num_flux_HLLC(Uj, Un, normal, gj);
 
       DUNE_THROW( Dune::NotImplemented, "Numerical flux not implemented" );
     }
@@ -142,28 +145,34 @@ namespace EulerNumFlux
     }
 
 
+    template <bool pottemp>
     FieldType num_flux_HLL(const FieldType Uj[dim+2], const FieldType Un[dim+2],
-                           const FieldType normal[dim], FieldType gj[dim+2]) const
+                           const FieldType normal[dim], FieldType gj[dim+2],
+                           const std::integral_constant<bool, pottemp> ) const
     {
+      static constexpr bool potentialTemperature = pottemp;
+
       const FieldType rhoj = Uj[0];
       FieldType Ej = Uj[dim+1];
       const FieldType rhon = Un[0];
       FieldType En = Un[dim+1];
-#ifdef POTTEMP
-      FieldType pressj, tempj;
-      FieldType pressn, tempn;
-      model_.pressAndTemp( Uj, pressj, tempj );
-      model_.pressAndTemp( Un, pressn, tempn );
-
-      FieldType Ekinj = 0;
-      FieldType Ekinn = 0;
-      for(int i=1; i<dim+1; i++){
-        Ekinj += (0.5/rhoj) * Uj[i] * Uj[i];
-        Ekinn += (0.5/rhon) * Un[i] * Un[i];
+
+      if constexpr (potentialTemperature)
+      {
+        FieldType pressj, tempj;
+        FieldType pressn, tempn;
+        model_.pressureTemperature( Uj, pressj, tempj );
+        model_.pressureTemperature( Un, pressn, tempn );
+
+        FieldType Ekinj = 0;
+        FieldType Ekinn = 0;
+        for(int i=1; i<dim+1; i++){
+          Ekinj += (0.5/rhoj) * Uj[i] * Uj[i];
+          Ekinn += (0.5/rhon) * Un[i] * Un[i];
+        }
+        Ej = pressj/(_gamma-1.) + Ekinj;
+        En = pressn/(_gamma-1.) + Ekinn;
       }
-      Ej = pressj/(_gamma-1.) + Ekinj;
-      En = pressn/(_gamma-1.) + Ekinn;
-#endif
 
       FieldType rho_uj[dim], rho_un[dim], uj[dim], un[dim];
       FieldType Ekin2j=0.0, Ekin2n=0.0;
@@ -204,11 +213,10 @@ namespace EulerNumFlux
           for(int i=0; i<dim; i++) guj[i] = rho_uj[i]*uj[0];
           guj[0] += pj;
 
-#ifdef POTTEMP
-          gj[dim+1] = Uj[dim+1]*uj[0];
-#else
-          gj[dim+1] = (Ej+pj)*uj[0];
-#endif
+          if constexpr (potentialTemperature)
+            gj[dim+1] = Uj[dim+1]*uj[0];
+          else
+            gj[dim+1] = (Ej+pj)*uj[0];
         }
         else{
           const FieldType tmp1 = sj * sn;
@@ -220,15 +228,18 @@ namespace EulerNumFlux
           }
           guj[0] += tmp2 * (sn*pj - sj*pn);
 
-#ifdef POTTEMP
-          const FieldType Etmpj = Uj[dim+1]*uj[0];
-          const FieldType Etmpn = Un[dim+1]*un[0];
-          gj[dim+1] = tmp2 * (sn*Etmpj-sj*Etmpn + tmp1*(Un[dim+1] - Uj[dim+1]));
-#else
-          const FieldType Etmpj = (Ej+pj)*uj[0];
-          const FieldType Etmpn = (En+pn)*un[0];
-          gj[dim+1] = tmp2 * (sn*Etmpj-sj*Etmpn + tmp1*(En - Ej));
-#endif
+          if constexpr(potentialTemperature)
+          {
+            const FieldType Etmpj = Uj[dim+1]*uj[0];
+            const FieldType Etmpn = Un[dim+1]*un[0];
+            gj[dim+1] = tmp2 * (sn*Etmpj-sj*Etmpn + tmp1*(Un[dim+1] - Uj[dim+1]));
+          }
+          else
+          {
+            const FieldType Etmpj = (Ej+pj)*uj[0];
+            const FieldType Etmpn = (En+pn)*un[0];
+            gj[dim+1] = tmp2 * (sn*Etmpj-sj*Etmpn + tmp1*(En - Ej));
+          }
         }
       }
       else{
@@ -238,11 +249,10 @@ namespace EulerNumFlux
           for(int i=0; i<dim; i++) guj[i] = rho_un[i]*un[0];
           guj[0] += pn;
 
-#ifdef POTTEMP
-          gj[dim+1] = Uj[dim+1]*un[0];
-#else
-          gj[dim+1] = (En+pn)*un[0];
-#endif
+          if constexpr(potentialTemperature)
+            gj[dim+1] = Uj[dim+1]*un[0];
+          else
+            gj[dim+1] = (En+pn)*un[0];
         }
         else{
           const FieldType tmp1 = sj * sn;
@@ -254,16 +264,18 @@ namespace EulerNumFlux
           }
           guj[0] += tmp2 * (sn*pj - sj*pn);
 
-#ifdef POTTEMP
-          const FieldType Etmpj = Uj[dim+1]*uj[0];
-          const FieldType Etmpn = Un[dim+1]*un[0];
-          gj[dim+1] = tmp2 * (sn*Etmpj-sj*Etmpn + tmp1*(Un[dim+1] - Uj[dim+1]));
-#else
-          const FieldType Etmpj = (Ej+pj)*uj[0];
-          const FieldType Etmpn = (En+pn)*un[0];
-          gj[dim+1] = tmp2 * (sn*Etmpj-sj*Etmpn + tmp1*(En - Ej));
-#endif
-
+          if constexpr(potentialTemperature)
+          {
+            const FieldType Etmpj = Uj[dim+1]*uj[0];
+            const FieldType Etmpn = Un[dim+1]*un[0];
+            gj[dim+1] = tmp2 * (sn*Etmpj-sj*Etmpn + tmp1*(Un[dim+1] - Uj[dim+1]));
+          }
+          else
+          {
+            const FieldType Etmpj = (Ej+pj)*uj[0];
+            const FieldType Etmpn = (En+pn)*un[0];
+            gj[dim+1] = tmp2 * (sn*Etmpj-sj*Etmpn + tmp1*(En - Ej));
+          }
         }
       }
 
@@ -482,7 +494,7 @@ namespace Fem
     /**
      * \copydoc DGAdvectionFluxBase::DGAdvectionFluxBase()
      */
-    EulerFluxImpl (const ModelImp& mod )
+    EulerFluxImpl (const ModelImp& mod, const ParameterType& parameter = ParameterType() )
       : BaseType( mod ),
         numFlux_( mod )
     {}
diff --git a/dune/fem-dg/operator/fluxes/euler/fluxes.hh b/dune/fem-dg/operator/fluxes/euler/fluxes.hh
index 55ea1fbb..4561e1cc 100644
--- a/dune/fem-dg/operator/fluxes/euler/fluxes.hh
+++ b/dune/fem-dg/operator/fluxes/euler/fluxes.hh
@@ -53,6 +53,25 @@ namespace Fem
     static std::string name () { return "HLL (Dennis)"; }
   };
 
+  /**
+   * \brief class specialization for the HLLC flux.
+   *
+   * The purpose of this class is to allow the selection of an Euler flux
+   * via an enum given in AdvectionFlux::Enum.
+   */
+  template< class Model >
+  class DGAdvectionFlux< Model, AdvectionFlux::Enum::euler_hll_pt >
+    : public EulerFluxImpl< Model, EulerNumFlux::EulerFlux<Model,EulerNumFlux::EulerFluxType::HLL_PT > >
+  {
+    typedef EulerFluxImpl< Model, EulerNumFlux::EulerFlux<Model,EulerNumFlux::EulerFluxType::HLL_PT > > BaseType ;
+  public:
+    template< class ... Args>
+    DGAdvectionFlux(  Args&&... args )
+      : BaseType( std::forward<Args>(args)... )
+    {}
+    static std::string name () { return "HLL_PT (Dennis)"; }
+  };
+
   /**
    * \brief class specialization for the HLLC flux.
    *
diff --git a/python/dune/femdg/patch.py b/python/dune/femdg/patch.py
index 04336da7..5a590e24 100644
--- a/python/dune/femdg/patch.py
+++ b/python/dune/femdg/patch.py
@@ -188,6 +188,16 @@ def codeFemDg(self, *args, **kwargs):
     predefined.update( {t: arg_t} )
     self.predefineCoefficients(predefined,'x')
 
+    # pressure and temperature for potential temperature formulation
+    pressureTemperature = getattr(Model,"pressureTemperature",None)
+    if pressureTemperature is not None:
+        pressureTemperature = pressureTemperature(u)
+    self.generateMethod(code, pressureTemperature,
+          'Dune::FieldVector<double, 2>', 'pressureTemperature',
+          args=['const State &u'],
+          targs=['class State'], const=True, inline=True,
+          predefined=predefined)
+
     maxWaveSpeed = getattr(Model,"maxWaveSpeed",None)
     # check for deprecated maxLambda
     if maxWaveSpeed is None:
-- 
GitLab