LCOV - code coverage report
Current view: top level - ugbase/lib_disc/spatial_disc/disc_util - conv_shape.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 197 0
Test Date: 2025-09-21 23:31:46 Functions: 0.0 % 264 0

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2011-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Andreas Vogel
       4              :  * 
       5              :  * This file is part of UG4.
       6              :  * 
       7              :  * UG4 is free software: you can redistribute it and/or modify it under the
       8              :  * terms of the GNU Lesser General Public License version 3 (as published by the
       9              :  * Free Software Foundation) with the following additional attribution
      10              :  * requirements (according to LGPL/GPL v3 §7):
      11              :  * 
      12              :  * (1) The following notice must be displayed in the Appropriate Legal Notices
      13              :  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
      14              :  * 
      15              :  * (2) The following notice must be displayed at a prominent place in the
      16              :  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
      17              :  * 
      18              :  * (3) The following bibliography is recommended for citation and must be
      19              :  * preserved in all covered files:
      20              :  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
      21              :  *   parallel geometric multigrid solver on hierarchically distributed grids.
      22              :  *   Computing and visualization in science 16, 4 (2013), 151-164"
      23              :  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
      24              :  *   flexible software system for simulating pde based models on high performance
      25              :  *   computers. Computing and visualization in science 16, 4 (2013), 165-179"
      26              :  * 
      27              :  * This program is distributed in the hope that it will be useful,
      28              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      29              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      30              :  * GNU Lesser General Public License for more details.
      31              :  */
      32              : 
      33              : #ifndef __H__UG__LIB_DISC__SPATIAL_DISC__ELEM_DISC__DENSITY_DRIVEN_FLOW__FV1__CONV_SHAPE__
      34              : #define __H__UG__LIB_DISC__SPATIAL_DISC__ELEM_DISC__DENSITY_DRIVEN_FLOW__FV1__CONV_SHAPE__
      35              : 
      36              : #include <boost/mpl/range_c.hpp>
      37              : #include <boost/mpl/for_each.hpp>
      38              : 
      39              : // ug4 headers
      40              : #include "conv_shape_interface.h"
      41              : #include "lib_disc/spatial_disc/disc_util/fv1_geom.h"
      42              : #include "lib_disc/spatial_disc/disc_util/hfv1_geom.h"
      43              : 
      44              : namespace ug{
      45              : 
      46              : /////////////////////////////////////////////////////////////////////////////
      47              : // No Upwind
      48              : /////////////////////////////////////////////////////////////////////////////
      49              : 
      50              : template <int TDim>
      51              : class ConvectionShapesNoUpwind
      52              :         : public IConvectionShapes<TDim>
      53              : {
      54              :         public:
      55              :         ///     Base class
      56              :                 typedef IConvectionShapes<TDim> base_type;
      57              : 
      58              :         ///     This class
      59              :                 typedef ConvectionShapesNoUpwind<TDim> this_type;
      60              : 
      61              :         ///     Dimension
      62              :                 static const int dim = TDim;
      63              : 
      64              :         protected:
      65              :         //      explicitly forward some function
      66              :                 using base_type::set_non_zero_deriv_diffusion_flag;
      67              :                 using base_type::conv_shape;
      68              :                 using base_type::D_vel;
      69              :                 using base_type::conv_shape_diffusion;
      70              :                 using base_type::non_zero_deriv_diffusion;
      71              :                 using base_type::register_update_func;
      72              : 
      73              :         public:
      74              :         ///     constructor
      75            0 :                 ConvectionShapesNoUpwind()
      76            0 :                 {
      77              :                 //      the shapes do not depend on the DiffDisp. Thus, we can set the
      78              :                 //      derivative to be always zero w.r.t. the DiffDisp for all shapes
      79              :                         set_non_zero_deriv_diffusion_flag(false);
      80              : 
      81              :                 //      register evaluation function
      82              :                         boost::mpl::for_each<typename domain_traits<dim>::AllElemList>(RegisterElemFunc(this));
      83              :                         boost::mpl::for_each< boost::mpl::range_c<int, 1, dim+1> >(RegisterRefDimFunc(this));
      84            0 :                 }
      85              : 
      86              :         ///     update of values for FV geometry
      87              :                 template <typename TFVGeom>
      88              :                 bool update(const TFVGeom* geo,
      89              :                                         const MathVector<dim>* Velocity,
      90              :                                         const MathMatrix<dim, dim>* DiffDisp,
      91              :                             bool computeDeriv);
      92              : 
      93              :         private:
      94              :                 
      95              :         ///     functor for registering the shapes for the element-templated FV geometries
      96              :                 struct RegisterElemFunc
      97              :                 {
      98              :                         this_type* m_pThis;
      99              :                         RegisterElemFunc(this_type * pThis) : m_pThis(pThis) {}
     100            0 :                         template<typename TElem> void operator() (TElem &)
     101              :                         {
     102            0 :                                 m_pThis->template register_func_for_elem_fvgeom< TElem, FV1Geometry<TElem, dim> >();
     103            0 :                                 m_pThis->template register_func_for_elem_fvgeom< TElem, FV1CondensedGeometry<TElem, dim> >();
     104            0 :                                 m_pThis->template register_func_for_elem_fvgeom< TElem, HFV1Geometry<TElem, dim> >();
     105            0 :                         }
     106              :                 };
     107              :         
     108              :         /// registers the update function for an element type and a FV geometry
     109              :                 template <typename TElem, typename TFVGeom>
     110              :                 void register_func_for_elem_fvgeom()
     111              :                 {
     112              :                         typedef bool (this_type::*TFunc) (const TFVGeom*, const MathVector<dim>*, const MathMatrix<dim, dim>*, bool);
     113            0 :                         base_type::template register_update_func<TFVGeom, TFunc>(&this_type::template update<TFVGeom>);
     114              :                 }
     115              :                 
     116              :         ///     functor for registering the shapes for the reference-dimension-templated FV geometries
     117              :                 struct RegisterRefDimFunc
     118              :                 {
     119              :                         this_type* m_pThis;
     120              :                         RegisterRefDimFunc(this_type * pThis) : m_pThis(pThis) {}
     121            0 :                         template<typename TRefDim> void operator() (TRefDim &) {m_pThis->register_func_for_refDim<TRefDim::value> ();}
     122              :                 };
     123              : 
     124              :         /// registers the update function for a reference dimension
     125              :                 template <int refDim>
     126              :                 void register_func_for_refDim()
     127              :                 {
     128              :                         typedef DimFV1Geometry<refDim, dim> TGeom;
     129              :                         typedef bool (this_type::*TFunc) (const TGeom*, const MathVector<dim>*, const MathMatrix<dim, dim>*, bool);
     130            0 :                         base_type::template register_update_func<TGeom, TFunc>(&this_type::template update<TGeom>);
     131              :                 }
     132              : };
     133              : 
     134              : template <int TDim>
     135              : template <typename TFVGeom>
     136              : bool
     137            0 : ConvectionShapesNoUpwind<TDim>::
     138              : update(const TFVGeom* geo,
     139              :        const MathVector<dim>* Velocity,
     140              :        const MathMatrix<dim, dim>* DiffDisp,
     141              :        bool computeDeriv)
     142              : {
     143              :         UG_ASSERT(geo != nullptr, "Null pointer");
     144              :         UG_ASSERT(Velocity != nullptr, "Null pointer");
     145              : 
     146              : //      \todo: think about: this should be something like scvf.num_sh()
     147              :         const size_t numSH = geo->num_sh();
     148              : 
     149              : //      loop subcontrol volume faces
     150            0 :         for(size_t ip = 0; ip < geo->num_scvf(); ++ip)
     151              :         {
     152              :         //      get subcontrol volume face
     153              :                 const typename TFVGeom::SCVF& scvf = geo->scvf(ip);
     154              : 
     155              :         //      Compute flux
     156            0 :                 const number flux = VecDot(scvf.normal(), Velocity[ip]);
     157              : 
     158              :         //      Write Shapes
     159            0 :                 for(size_t sh = 0; sh < scvf.num_sh(); sh++)
     160            0 :                         conv_shape(ip, sh) = flux * scvf.shape(sh);
     161              : 
     162              :         //      this is introduced here, hopefully temporarily: The problem is, that
     163              :         //      for hanging nodes the number of shape function is not the number of
     164              :         //      corners, but scvf.num_sh() currently returns the number of corners.
     165              :         //      this is actually enough to interpolate the function, but still we
     166              :         //      should reset the interpolation adding for hanging dofs to zero
     167            0 :                 for(size_t sh = scvf.num_sh(); sh < numSH; sh++)
     168            0 :                         conv_shape(ip, sh) = 0.0;
     169              : 
     170              :         //      Write Derivatives if wanted
     171            0 :                 if(computeDeriv){
     172            0 :                         for (size_t sh = 0; sh < scvf.num_sh(); sh++)
     173              :                                 VecScale(D_vel(ip, sh), scvf.normal(), scvf.shape(sh));
     174              : 
     175              :                         // temporary, see above
     176            0 :                         for(size_t sh = scvf.num_sh(); sh < numSH; sh++)
     177              :                                 VecSet(D_vel(ip, sh), 0.0);
     178              :                 }
     179              : 
     180              :         //      The shapes do not depend of the diffusion tensor
     181              :         }
     182              : 
     183              : //      we're done
     184            0 :         return true;
     185              : }
     186              : 
     187              : /////////////////////////////////////////////////////////////////////////////
     188              : // Full Upwind
     189              : /////////////////////////////////////////////////////////////////////////////
     190              : 
     191              : template <int TDim>
     192              : class ConvectionShapesFullUpwind
     193              :         : public IConvectionShapes<TDim>
     194              : {
     195              :         public:
     196              :         ///     Base class
     197              :                 typedef IConvectionShapes<TDim> base_type;
     198              : 
     199              :         ///     This class
     200              :                 typedef ConvectionShapesFullUpwind<TDim> this_type;
     201              : 
     202              :         ///     Dimension
     203              :                 static const int dim = TDim;
     204              : 
     205              :         protected:
     206              :         //      explicitly forward some function
     207              :                 using base_type::set_non_zero_deriv_diffusion_flag;
     208              :                 using base_type::conv_shape;
     209              :                 using base_type::D_vel;
     210              :                 using base_type::conv_shape_diffusion;
     211              :                 using base_type::non_zero_deriv_diffusion;
     212              :                 using base_type::register_update_func;
     213              : 
     214              :         public:
     215              :         ///     constructor
     216            0 :                 ConvectionShapesFullUpwind()
     217            0 :                 {
     218              :                 //      the shapes do not depend on the DiffDisp. Thus, we can set the
     219              :                 //      derivative to be always zero w.r.t. the DiffDisp for all shapes
     220              :                         set_non_zero_deriv_diffusion_flag(false);
     221              : 
     222              :                 //      register evaluation function
     223              :                         boost::mpl::for_each<typename domain_traits<dim>::AllElemList>(RegisterElemFunc(this));
     224              :                         boost::mpl::for_each< boost::mpl::range_c<int, 1, dim+1> >(RegisterRefDimFunc(this));
     225            0 :                 }
     226              : 
     227              :         ///     update of values for FV1Geometry
     228              :                 template <typename TFVGeom>
     229              :                 bool update(const TFVGeom* geo,
     230              :                                         const MathVector<dim>* Velocity,
     231              :                                         const MathMatrix<dim, dim>* DiffDisp,
     232              :                             bool computeDeriv);
     233              : 
     234              :         private:
     235              :                 
     236              :         ///     functor for registering the shapes for the element-templated FV geometries
     237              :                 struct RegisterElemFunc
     238              :                 {
     239              :                         this_type* m_pThis;
     240              :                         RegisterElemFunc(this_type * pThis) : m_pThis(pThis) {}
     241            0 :                         template<typename TElem> void operator() (TElem &)
     242              :                         {
     243            0 :                                 m_pThis->template register_func_for_elem_fvgeom< TElem, FV1Geometry<TElem, dim> >();
     244            0 :                                 m_pThis->template register_func_for_elem_fvgeom< TElem, FV1CondensedGeometry<TElem, dim> >();
     245            0 :                                 m_pThis->template register_func_for_elem_fvgeom< TElem, HFV1Geometry<TElem, dim> >();
     246            0 :                         }
     247              :                 };
     248              :         
     249              :         /// registers the update function for an element type and a FV geometry
     250              :                 template <typename TElem, typename TFVGeom>
     251              :                 void register_func_for_elem_fvgeom()
     252              :                 {
     253              :                         typedef bool (this_type::*TFunc) (const TFVGeom*, const MathVector<dim>*, const MathMatrix<dim, dim>*, bool);
     254            0 :                         base_type::template register_update_func<TFVGeom, TFunc>(&this_type::template update<TFVGeom>);
     255              :                 }
     256              :                 
     257              :         ///     functor for registering the shapes for the reference-dimension-templated FV geometries
     258              :                 struct RegisterRefDimFunc
     259              :                 {
     260              :                         this_type* m_pThis;
     261              :                         RegisterRefDimFunc(this_type * pThis) : m_pThis(pThis) {}
     262            0 :                         template<typename TRefDim> void operator() (TRefDim &) {m_pThis->register_func_for_refDim<TRefDim::value> ();}
     263              :                 };
     264              : 
     265              :         /// registers the update function for a reference dimension
     266              :                 template <int refDim>
     267              :                 void register_func_for_refDim()
     268              :                 {
     269              :                         typedef DimFV1Geometry<refDim, dim> TGeom;
     270              :                         typedef bool (this_type::*TFunc) (const TGeom*, const MathVector<dim>*, const MathMatrix<dim, dim>*, bool);
     271            0 :                         base_type::template register_update_func<TGeom, TFunc>(&this_type::template update<TGeom>);
     272              :                 }
     273              : };
     274              : 
     275              : template <int TDim>
     276              : template <typename TFVGeom>
     277            0 : bool ConvectionShapesFullUpwind<TDim>::
     278              : update(const TFVGeom* geo,
     279              :        const MathVector<dim>* Velocity,
     280              :        const MathMatrix<dim, dim>* DiffDisp,
     281              :        bool computeDeriv)
     282              : {
     283              :         UG_ASSERT(geo != nullptr, "Null pointer");
     284              :         UG_ASSERT(Velocity != nullptr, "Null pointer");
     285              : 
     286              : //      \todo: think about: this should be something like scvf.num_sh()
     287              :         const size_t numSH = geo->num_sh();
     288              : 
     289              : //      loop subcontrol volume faces
     290            0 :         for(size_t ip = 0; ip < geo->num_scvf(); ++ip)
     291              :         {
     292              :         //      get subcontrol volume face
     293              :                 const typename TFVGeom::SCVF& scvf = geo->scvf(ip);
     294              : 
     295              :         //      Compute flux
     296            0 :                 const number flux = VecDot(scvf.normal(), Velocity[ip]);
     297              : 
     298              :                 size_t from = scvf.from();
     299              :                 size_t to = scvf.to();
     300              : 
     301              :         //      if e.g. hanging nodes are involved, no upwind can be performed...               
     302            0 :                 if((from >= scvf.num_sh()) || (to >= scvf.num_sh())){
     303              :                 //      No upwind...
     304              :                 //      Write Shapes
     305            0 :                         for(size_t sh = 0; sh < scvf.num_sh(); sh++)
     306            0 :                                 conv_shape(ip, sh) = flux * scvf.shape(sh);
     307              : 
     308              :                         UG_ASSERT(scvf.num_sh() == numSH, "sh's have to match!");
     309              : 
     310              :                 //      Write Derivatives if wanted
     311            0 :                         if(computeDeriv){
     312            0 :                                 for (size_t sh = 0; sh < scvf.num_sh(); sh++)
     313              :                                         VecScale(D_vel(ip, sh), scvf.normal(), scvf.shape(sh));
     314              :                         }
     315              :                         
     316            0 :                         continue;
     317            0 :                 }
     318              :                 
     319              :         //      Full upwind below...
     320              :         //      Choose Upwind corner
     321            0 :                 size_t up = (flux >= 0) ? from : to;
     322              : 
     323              :         //      Write Shapes
     324            0 :                 for(size_t sh = 0; sh < scvf.num_sh(); ++sh) conv_shape(ip, sh) = 0.0;
     325              : 
     326            0 :                 conv_shape(ip, up) = flux;
     327              : 
     328              :         //      Write Derivatives if wanted
     329            0 :                 if(computeDeriv)
     330              :                 {
     331            0 :                         for(size_t sh = 0; sh < numSH; ++sh) VecSet(D_vel(ip, sh), 0.0);
     332              :                         D_vel(ip, up) = scvf.normal();
     333              :                 }
     334              : 
     335              :         //      The shapes do not depend of the diffusion tensor
     336              :         }
     337              : 
     338              : //      we're done
     339            0 :         return true;
     340              : }
     341              : 
     342              : /////////////////////////////////////////////////////////////////////////////
     343              : // Weighted Upwind
     344              : /////////////////////////////////////////////////////////////////////////////
     345              : 
     346              : template <int TDim>
     347              : class ConvectionShapesWeightedUpwind
     348              :         : public IConvectionShapes<TDim>
     349              : {
     350              :         public:
     351              :         ///     Base class
     352              :                 typedef IConvectionShapes<TDim> base_type;
     353              : 
     354              :         ///     This class
     355              :                 typedef ConvectionShapesWeightedUpwind<TDim> this_type;
     356              : 
     357              :         ///     Dimension
     358              :                 static const int dim = TDim;
     359              : 
     360              :         protected:
     361              :         //      explicitly forward some function
     362              :                 using base_type::set_non_zero_deriv_diffusion_flag;
     363              :                 using base_type::conv_shape;
     364              :                 using base_type::D_vel;
     365              :                 using base_type::conv_shape_diffusion;
     366              :                 using base_type::non_zero_deriv_diffusion;
     367              :                 using base_type::register_update_func;
     368              : 
     369              :         public:
     370              :         ///     constructor
     371            0 :                 ConvectionShapesWeightedUpwind() : m_weight(0.5)
     372              :                 {
     373              :                 //      the shapes do not depend on the DiffDisp. Thus, we can set the
     374              :                 //      derivative to be always zero w.r.t. the DiffDisp for all shapes
     375              :                         set_non_zero_deriv_diffusion_flag(false);
     376              : 
     377              :                 //      register evaluation function
     378              :                         boost::mpl::for_each<typename domain_traits<dim>::AllElemList>(RegisterElemFunc(this));
     379              :                         boost::mpl::for_each< boost::mpl::range_c<int, 1, dim+1> >(RegisterRefDimFunc(this));
     380            0 :                 }
     381              : 
     382              :         ///     constructor
     383            0 :                 ConvectionShapesWeightedUpwind(number weight)
     384            0 :                 {
     385              :                         set_weight(weight);
     386              : 
     387              :                 //      the shapes do not depend on the DiffDisp. Thus, we can set the
     388              :                 //      derivative to be always zero w.r.t. the DiffDisp for all shapes
     389              :                         set_non_zero_deriv_diffusion_flag(false);
     390              : 
     391              :                 //      register evaluation function
     392              :                         boost::mpl::for_each<typename domain_traits<dim>::AllElemList>(RegisterElemFunc(this));
     393              :                         boost::mpl::for_each< boost::mpl::range_c<int, 1, dim+1> >(RegisterRefDimFunc(this));
     394            0 :                 }
     395              : 
     396              :         ///     set weighting between full upwind (1.0) and no upwind (0.0)
     397            0 :                 void set_weight(number weight) {m_weight = weight;}
     398              : 
     399              :         ///     update of values for FV1Geometry
     400              :                 template <typename TFVGeom>
     401              :                 bool update(const TFVGeom* geo,
     402              :                                         const MathVector<dim>* Velocity,
     403              :                                         const MathMatrix<dim, dim>* DiffDisp,
     404              :                             bool computeDeriv);
     405              : 
     406              :         private:
     407              :         //      weight between no and full upwind (1.0 -> full upwind, 0.0 -> no upwind)
     408              :                 number m_weight;
     409              :                 
     410              :         private:
     411              :         
     412              :         ///     functor for registering the shapes for the element-templated FV geometries
     413              :                 struct RegisterElemFunc
     414              :                 {
     415              :                         this_type* m_pThis;
     416              :                         RegisterElemFunc(this_type * pThis) : m_pThis(pThis) {}
     417            0 :                         template<typename TElem> void operator() (TElem &)
     418              :                         {
     419            0 :                                 m_pThis->template register_func_for_elem_fvgeom< TElem, FV1Geometry<TElem, dim> >();
     420            0 :                                 m_pThis->template register_func_for_elem_fvgeom< TElem, FV1CondensedGeometry<TElem, dim> >();
     421            0 :                                 m_pThis->template register_func_for_elem_fvgeom< TElem, HFV1Geometry<TElem, dim> >();
     422            0 :                         }
     423              :                 };
     424              :         
     425              :         /// registers the update function for an element type and a FV geometry
     426              :                 template <typename TElem, typename TFVGeom>
     427              :                 void register_func_for_elem_fvgeom()
     428              :                 {
     429              :                         typedef bool (this_type::*TFunc) (const TFVGeom*, const MathVector<dim>*, const MathMatrix<dim, dim>*, bool);
     430            0 :                         base_type::template register_update_func<TFVGeom, TFunc>(&this_type::template update<TFVGeom>);
     431              :                 }
     432              :                 
     433              :         ///     functor for registering the shapes for the reference-dimension-templated FV geometries
     434              :                 struct RegisterRefDimFunc
     435              :                 {
     436              :                         this_type* m_pThis;
     437              :                         RegisterRefDimFunc(this_type * pThis) : m_pThis(pThis) {}
     438            0 :                         template<typename TRefDim> void operator() (TRefDim &) {m_pThis->register_func_for_refDim<TRefDim::value> ();}
     439              :                 };
     440              : 
     441              :         /// registers the update function for a reference dimension
     442              :                 template <int refDim>
     443              :                 void register_func_for_refDim()
     444              :                 {
     445              :                         typedef DimFV1Geometry<refDim, dim> TGeom;
     446              :                         typedef bool (this_type::*TFunc) (const TGeom*, const MathVector<dim>*, const MathMatrix<dim, dim>*, bool);
     447            0 :                         base_type::template register_update_func<TGeom, TFunc>(&this_type::template update<TGeom>);
     448              :                 }
     449              : };
     450              : 
     451              : template <int TDim>
     452              : template <typename TFVGeom>
     453            0 : bool ConvectionShapesWeightedUpwind<TDim>::
     454              : update(const TFVGeom* geo,
     455              :        const MathVector<dim>* Velocity,
     456              :        const MathMatrix<dim, dim>* DiffDisp,
     457              :        bool computeDeriv)
     458              : {
     459              :         UG_ASSERT(geo != nullptr, "Null pointer");
     460              :         UG_ASSERT(Velocity != nullptr, "Null pointer");
     461              : 
     462              : //      \todo: think about: this should be something like scvf.num_sh()
     463              :         const size_t numSH = geo->num_sh();
     464              : 
     465              : //      loop subcontrol volume faces
     466            0 :         for(size_t ip = 0; ip < geo->num_scvf(); ++ip)
     467              :         {
     468              :         //      get subcontrol volume face
     469              :                 const typename TFVGeom::SCVF& scvf = geo->scvf(ip);
     470              : 
     471              :         //      Compute flux
     472            0 :                 const number flux = VecDot(scvf.normal(), Velocity[ip]);
     473              : 
     474              :                 size_t from = scvf.from();
     475              :                 size_t to = scvf.to();
     476              : 
     477              :         //      if e.g. hanging nodes are involved, no upwind can be performed...               
     478            0 :                 if((from >= scvf.num_sh()) || (to >= scvf.num_sh())){
     479              :                 //      No upwind...
     480              :                 //      Write Shapes
     481            0 :                         for(size_t sh = 0; sh < scvf.num_sh(); sh++)
     482            0 :                                 conv_shape(ip, sh) = flux * scvf.shape(sh);
     483              : 
     484              :                         UG_ASSERT(scvf.num_sh() == numSH, "sh's have to match!");
     485              : 
     486              :                 //      Write Derivatives if wanted
     487            0 :                         if(computeDeriv){
     488            0 :                                 for (size_t sh = 0; sh < scvf.num_sh(); sh++)
     489              :                                         VecScale(D_vel(ip, sh), scvf.normal(), scvf.shape(sh));
     490              :                         }
     491              :                         
     492            0 :                         continue;
     493            0 :                 }
     494              :                 
     495              :         //      Choose Upwind corner
     496            0 :                 size_t up = (flux >= 0) ? from : to;
     497              :                 
     498              :         //      write no upwind part of shapes
     499            0 :                 const number noUpFlux = (1.-m_weight)*flux;
     500            0 :                 for(size_t sh = 0; sh < scvf.num_sh(); ++sh)
     501            0 :                         conv_shape(ip, sh) = noUpFlux * scvf.shape(sh);
     502              : 
     503              :         //      add full upwind part of shapes
     504            0 :                 conv_shape(ip, up) += m_weight * flux;
     505              : 
     506              :         //      Write Derivatives if wanted
     507            0 :                 if(computeDeriv)
     508              :                 {
     509              :                 //      write no upwind part of derivatives
     510            0 :                         for (size_t sh = 0; sh < scvf.num_sh(); sh++)
     511            0 :                                 VecScale(D_vel(ip, sh), scvf.normal(),
     512            0 :                                                                                  (1.-m_weight)*scvf.shape(sh));
     513              :                 //      see comment above
     514            0 :                         for(size_t sh = scvf.num_sh(); sh < numSH; sh++)
     515              :                                 VecSet(D_vel(ip, sh), 0.0);
     516              : 
     517              :                 //      add full upwind part of derivatives
     518            0 :                         VecScaleAppend(D_vel(ip, up), m_weight, scvf.normal());
     519              :                 }
     520              : 
     521              :         //      The shapes do not depend of the diffusion tensor
     522              :         }
     523              : 
     524              : //      we're done
     525            0 :         return true;
     526              : }
     527              : 
     528              : 
     529              : /////////////////////////////////////////////////////////////////////////////
     530              : // Partial Upwind
     531              : /////////////////////////////////////////////////////////////////////////////
     532              : 
     533              : template <int TDim>
     534              : class ConvectionShapesPartialUpwind
     535              :         : public IConvectionShapes<TDim>
     536              : {
     537              :         public:
     538              :         ///     Base class
     539              :                 typedef IConvectionShapes<TDim> base_type;
     540              : 
     541              :         ///     This class
     542              :                 typedef ConvectionShapesPartialUpwind<TDim> this_type;
     543              : 
     544              :         ///     Dimension
     545              :                 static const int dim = TDim;
     546              : 
     547              :         protected:
     548              :         //      explicitly forward some function
     549              :                 using base_type::set_non_zero_deriv_diffusion_flag;
     550              :                 using base_type::conv_shape;
     551              :                 using base_type::D_vel;
     552              :                 using base_type::conv_shape_diffusion;
     553              :                 using base_type::non_zero_deriv_diffusion;
     554              :                 using base_type::register_update_func;
     555              : 
     556              :         public:
     557              :         ///     constructor
     558            0 :                 ConvectionShapesPartialUpwind()
     559            0 :                 {
     560              :                 //      register evaluation function
     561              :                         boost::mpl::for_each<typename domain_traits<dim>::AllElemList>(RegisterElemFunc(this));
     562              :                         boost::mpl::for_each< boost::mpl::range_c<int, 1, dim+1> >(RegisterRefDimFunc(this));
     563            0 :                 }
     564              : 
     565              :         ///     update of values for FV1Geometry
     566              :                 template <typename TFVGeom>
     567              :                 bool update(const TFVGeom* geo,
     568              :                                         const MathVector<dim>* Velocity,
     569              :                                         const MathMatrix<dim, dim>* DiffDisp,
     570              :                                         bool computeDeriv);
     571              : 
     572              :         private:
     573              :                 
     574              :         ///     functor for registering the shapes for the element-templated FV geometries
     575              :                 struct RegisterElemFunc
     576              :                 {
     577              :                         this_type* m_pThis;
     578              :                         RegisterElemFunc(this_type * pThis) : m_pThis(pThis) {}
     579            0 :                         template<typename TElem> void operator() (TElem &)
     580              :                         {
     581            0 :                                 m_pThis->template register_func_for_elem_fvgeom< TElem, FV1Geometry<TElem, dim> >();
     582            0 :                                 m_pThis->template register_func_for_elem_fvgeom< TElem, FV1CondensedGeometry<TElem, dim> >();
     583            0 :                         }
     584              :                 };
     585              :         
     586              :         /// registers the update function for an element type and a FV geometry
     587              :                 template <typename TElem, typename TFVGeom>
     588              :                 void register_func_for_elem_fvgeom()
     589              :                 {
     590              :                         typedef bool (this_type::*TFunc) (const TFVGeom*, const MathVector<dim>*, const MathMatrix<dim, dim>*, bool);
     591            0 :                         base_type::template register_update_func<TFVGeom, TFunc>(&this_type::template update<TFVGeom>);
     592              :                 }
     593              :                 
     594              :         ///     functor for registering the shapes for the reference-dimension-templated FV geometries
     595              :                 struct RegisterRefDimFunc
     596              :                 {
     597              :                         this_type* m_pThis;
     598              :                         RegisterRefDimFunc(this_type * pThis) : m_pThis(pThis) {}
     599            0 :                         template<typename TRefDim> void operator() (TRefDim &) {m_pThis->register_func_for_refDim<TRefDim::value> ();}
     600              :                 };
     601              : 
     602              :         /// registers the update function for a reference dimension
     603              :                 template <int refDim>
     604              :                 void register_func_for_refDim()
     605              :                 {
     606              :                         typedef DimFV1Geometry<refDim, dim> TGeom;
     607              :                         typedef bool (this_type::*TFunc) (const TGeom*, const MathVector<dim>*, const MathMatrix<dim, dim>*, bool);
     608            0 :                         base_type::template register_update_func<TGeom, TFunc>(&this_type::template update<TGeom>);
     609              :                 }
     610              : };
     611              : 
     612              : template <int TDim>
     613              : template <typename TFVGeom>
     614              : bool
     615            0 : ConvectionShapesPartialUpwind<TDim>::
     616              : update(const TFVGeom* geo,
     617              :        const MathVector<dim>* Velocity,
     618              :        const MathMatrix<dim, dim>* DiffDisp,
     619              :        bool computeDeriv)
     620              : {
     621              :         UG_ASSERT(geo != nullptr, "Null pointer");
     622              :         UG_ASSERT(Velocity != nullptr, "Null pointer");
     623              : //      UG_ASSERT(DiffDisp != nullptr, "Null pointer");
     624              : 
     625              : //      Compute Volume of Element
     626              : //      typedef typename TFVGeom::ref_elem_type ref_elem_type;
     627            0 :         const number vol = ElementSize<dim>(geo->roid(), geo->corners());
     628              : 
     629              : //      loop subcontrol volume faces
     630            0 :         for(size_t i = 0; i < geo->num_scvf(); ++i)
     631              :         {
     632              :         //      get subcontrol volume face
     633              :                 const typename TFVGeom::SCVF& scvf = geo->scvf(i);
     634              : 
     635              :         //      get corners
     636              :                 const size_t from = scvf.from();
     637              :                 const size_t to = scvf.to();
     638              : 
     639              :         //      get gradients
     640              :                 const MathVector<dim>& gradTo = scvf.global_grad(to);
     641              :                 const MathVector<dim>& gradFrom = scvf.global_grad(from);
     642              : 
     643              :         //      set lambda negative as default
     644              :                 number lambda = -1;
     645              : 
     646              :         //      if DiffDisp-Tensor passed, compute lambda
     647            0 :                 if(DiffDisp != nullptr)
     648              :                 {
     649              :                 //  Get Gradients
     650              :                         MathVector<dim> DiffGrad;
     651              : 
     652              :                 //      Compute DiffGrad = D * Grad Phi_to
     653            0 :                         MatVecMult(DiffGrad, DiffDisp[i], gradTo);
     654              : 
     655              :                 //      Compute GradDiffGrad = < Grad Phi_from, DiffGrad >
     656              :                         const number GradDiffGrad = VecDot(DiffGrad,  gradFrom);
     657              : 
     658              :                 //      Set lambda
     659            0 :                         lambda = - GradDiffGrad * vol;
     660              :                 }
     661              : 
     662              :                 //      Compute flux
     663            0 :         const number flux = VecDot(scvf.normal(), Velocity[i]);
     664              : 
     665              :         //      reset values
     666            0 :         for (size_t sh = 0; sh < scvf.num_sh(); ++sh)
     667            0 :                 conv_shape(i, sh) = 0.0;
     668            0 :         if (computeDeriv)
     669            0 :                 for (size_t sh = 0; sh < scvf.num_sh(); ++sh) {
     670              :                         VecSet(D_vel(i, sh), 0.0);
     671              :                         MatSet(conv_shape_diffusion(i, sh), 0.0);
     672              :                 }
     673              : 
     674              : 
     675              :         //      check: Currently hanging nodes not supported.
     676              :         //      /todo: add support for hanging nodes
     677            0 :         if (from >= scvf.num_sh() || to >= scvf.num_sh())
     678            0 :         UG_THROW("PartialUpwind: Currently not implemented for hanging nodes.")
     679              : 
     680              :         ///////////////////////////////////////////////////////////////////
     681              :         //      Case 1:
     682              :         //      full upwind is used
     683              :         ///////////////////////////////////////////////////////////////////
     684            0 :                 if(lambda <= 0 || DiffDisp == nullptr)
     685              :                 {
     686              :                 //      Choose Upwind corner
     687            0 :                         const size_t up = (flux >= 0) ? scvf.from() : scvf.to();
     688              : 
     689              :                 //      Write Shapes
     690            0 :                         conv_shape(i, up) = flux;
     691              : 
     692              :                 //      Write Derivatives if wanted
     693            0 :                         if(computeDeriv)
     694              :                         {
     695              :                         //      set derivative
     696              :                                 D_vel(i, up) = scvf.normal();
     697              : 
     698              :                         //      does not depend on diffusion
     699              :                                 set_non_zero_deriv_diffusion_flag(false);
     700              :                         }
     701              : 
     702              :                 //      everything done
     703            0 :                         continue;
     704            0 :                 }
     705              : 
     706              :         ///////////////////////////////////////////////////////////////////
     707              :         //      Case 2:
     708              :         //      The case of the diffusion dominance (central differences)
     709              :         ///////////////////////////////////////////////////////////////////
     710            0 :                 if (2 * lambda > fabs(flux))
     711              :                 {
     712            0 :                         conv_shape(i, from) = flux / 2.0;
     713            0 :                         conv_shape(i, to) = flux / 2.0;
     714              : 
     715            0 :                         if(computeDeriv)
     716              :                         {
     717              :                                 set_non_zero_deriv_diffusion_flag(false);
     718              : 
     719              :                                 VecScale(D_vel(i,from), scvf.normal(), 1.0/2.0);
     720              :                                 VecScale(D_vel(i, to), scvf.normal(), 1.0/2.0);
     721              :                         }
     722              : 
     723              :                 //      everything done
     724            0 :                         continue;
     725              :                 }
     726              : 
     727              :         ///////////////////////////////////////////////////////////////////
     728              :         //      Case 3:
     729              :         //      The cases of the convection dominance
     730              :         ///////////////////////////////////////////////////////////////////
     731              :                 set_non_zero_deriv_diffusion_flag(true);
     732            0 :                 if (flux >= 0)
     733              :                 {
     734            0 :                         conv_shape(i, from) = flux - lambda;
     735            0 :                         conv_shape(i, to) = lambda;
     736              : 
     737            0 :                         if(computeDeriv)
     738              :                                 D_vel(i,from) = scvf.normal();
     739              :                 }
     740              :                 else
     741              :                 {
     742            0 :                         conv_shape(i, from) = - lambda;
     743            0 :                         conv_shape(i, to) = flux + lambda;
     744              : 
     745            0 :                         if(computeDeriv)
     746              :                                 D_vel(i,to) = scvf.normal();
     747              :                 }
     748              : 
     749            0 :                 if (computeDeriv)
     750              :                 {
     751            0 :                         for (size_t k = 0; k < (size_t)dim; k++)
     752            0 :                                 for (size_t l = 0; l < (size_t)dim; l++)
     753              :                                 {
     754            0 :                                         conv_shape_diffusion(i, from)(k,l) = gradFrom[k]*gradTo[l]*vol;
     755            0 :                                         conv_shape_diffusion(i, to)(k,l) = - gradFrom[k]*gradTo[l]*vol;
     756              :                                 }
     757              :                 }
     758              :         }
     759              : 
     760              : //      we're done
     761            0 :         return true;
     762              : }
     763              : 
     764              : /////////////////////////////////////////////////////////////////////////////
     765              : // Skewed Upwind
     766              : /////////////////////////////////////////////////////////////////////////////
     767              : 
     768              : template <int TDim>
     769              : class ConvectionShapesSkewedUpwind
     770              :         : public IConvectionShapes<TDim>
     771              : {
     772              : public:
     773              :         ///     Base class
     774              :         typedef IConvectionShapes<TDim> base_type;
     775              : 
     776              :         ///     This class
     777              :         typedef ConvectionShapesSkewedUpwind<TDim> this_type;
     778              : 
     779              :         ///     Dimension
     780              :         static const int dim = TDim;
     781              : 
     782              : protected:
     783              :         //      explicitly forward some function
     784              :         using base_type::conv_shape;
     785              :         using base_type::conv_shape_diffusion;
     786              :         using base_type::D_vel;
     787              :         using base_type::non_zero_deriv_diffusion;
     788              :         using base_type::register_update_func;
     789              :         using base_type::set_non_zero_deriv_diffusion_flag;
     790              : 
     791              : public:
     792              :         ///     constructor
     793            0 :         ConvectionShapesSkewedUpwind()
     794            0 :         {
     795              :                 //      the shapes do not depend on the DiffDisp. Thus, we can set the
     796              :                 //      derivative to be always zero w.r.t. the DiffDisp for all shapes
     797              :                 set_non_zero_deriv_diffusion_flag(false);
     798              : 
     799              :                 //      register evaluation function
     800              :                 boost::mpl::for_each<typename domain_traits<dim>::AllElemList>(RegisterElemFunc(this));
     801              :                 boost::mpl::for_each<boost::mpl::range_c<int, 1, dim + 1>>(RegisterRefDimFunc(this));
     802            0 :         }
     803              : 
     804              :         ///     update of values for FV geometry
     805              :         template <typename TFVGeom>
     806              :         bool update(const TFVGeom *geo,
     807              :                                 const MathVector<dim> *Velocity,
     808              :                                 const MathMatrix<dim, dim> *DiffDisp,
     809              :                                 bool computeDeriv);
     810              : 
     811              : private:
     812              :         ///     functor for registering the shapes for the element-templated FV geometries
     813              :         struct RegisterElemFunc
     814              :         {
     815              :                 this_type *m_pThis;
     816              :                 RegisterElemFunc(this_type *pThis) : m_pThis(pThis) {}
     817              :                 template <typename TElem>
     818              :                 void operator()(TElem &)
     819              :                 {
     820            0 :                         m_pThis->template register_func_for_elem_fvgeom<TElem, FV1Geometry<TElem, dim>>();
     821              :                         //m_pThis->template register_func_for_elem_fvgeom< TElem, FV1CondensedGeometry<TElem, dim> >();
     822              :                         //m_pThis->template register_func_for_elem_fvgeom< TElem, HFV1Geometry<TElem, dim> >();
     823            0 :                 }
     824              :         };
     825              : 
     826              :         /// registers the update function for an element type and a FV geometry
     827              :         template <typename TElem, typename TFVGeom>
     828              :         void register_func_for_elem_fvgeom()
     829              :         {
     830              :                 typedef bool (this_type::*TFunc)(const TFVGeom *, const MathVector<dim> *, const MathMatrix<dim, dim> *, bool);
     831            0 :                 base_type::template register_update_func<TFVGeom, TFunc>(&this_type::template update<TFVGeom>);
     832              :         }
     833              : 
     834              :         ///     functor for registering the shapes for the reference-dimension-templated FV geometries
     835              :         struct RegisterRefDimFunc
     836              :         {
     837              :                 this_type *m_pThis;
     838              :                 RegisterRefDimFunc(this_type *pThis) : m_pThis(pThis) {}
     839              :                 template <typename TRefDim>
     840              :                 void operator()(TRefDim &) { m_pThis->register_func_for_refDim<TRefDim::value>(); }
     841              :         };
     842              : 
     843              :         /// registers the update function for a reference dimension
     844              :         template <int refDim>
     845              :         void register_func_for_refDim()
     846              :         {
     847              :                 //typedef DimFV1Geometry<refDim, dim> TGeom;
     848              :                 //typedef bool (this_type::*TFunc) (const TGeom*, const MathVector<dim>*, const MathMatrix<dim, dim>*, bool);
     849              :                 //base_type::template register_update_func<TGeom, TFunc>(&this_type::template update<TGeom>);
     850              :         }
     851              : };
     852              : 
     853              : /// computes the closest node to a elem side ray intersection
     854              : template <typename TRefElem, int TWorldDim>
     855            0 : void GetNodeNextToCut(size_t &coOut,
     856              :                                           const MathVector<TWorldDim> &IP,
     857              :                                           const MathVector<TWorldDim> &IPVel,
     858              :                                           const MathVector<TWorldDim> *vCornerCoords)
     859              : {
     860              :         //      help variables
     861            0 :         size_t side = 0;
     862              :         MathVector<TWorldDim> globalIntersection;
     863              :         MathVector<TRefElem::dim> localIntersection;
     864              : 
     865              :         //      compute intersection of ray in direction of ip velocity with elem side
     866              :         //      we search the ray only in upwind direction
     867            0 :         if (!ElementSideRayIntersection<TRefElem, TWorldDim>(side, globalIntersection, localIntersection,
     868              :                                                                                                                  IP, IPVel, false /* i.e. search upwind */, vCornerCoords))
     869            0 :                 UG_THROW("GetNodeNextToCut: ElementSideRayIntersection failed");
     870              : 
     871              :         //      get reference element
     872            0 :         static const TRefElem &rRefElem = Provider<TRefElem>::get();
     873              :         const int dim = TRefElem::dim;
     874              : 
     875              :         //      reset minimum
     876              :         number min = std::numeric_limits<number>::max();
     877              : 
     878              :         //      loop corners of side
     879            0 :         for (size_t i = 0; i < rRefElem.num(dim - 1, side, 0); ++i)
     880              :         {
     881              :                 //      get corner
     882            0 :                 const size_t co = rRefElem.id(dim - 1, side, 0, i);
     883              : 
     884              :                 //      Compute Distance to intersection
     885            0 :                 number dist = VecDistanceSq(globalIntersection, vCornerCoords[co]);
     886              : 
     887              :                 //      if distance is smaller, choose this node
     888            0 :                 if (dist < min)
     889              :                 {
     890              :                         min = dist;
     891            0 :                         coOut = co;
     892              :                 }
     893              :         }
     894            0 : }
     895              : 
     896              : template <int TDim>
     897              : template <typename TFVGeom>
     898            0 : bool ConvectionShapesSkewedUpwind<TDim>::
     899              :         update(const TFVGeom *geo,
     900              :                    const MathVector<dim> *Velocity,
     901              :                    const MathMatrix<dim, dim> *DiffDisp,
     902              :                    bool computeDeriv)
     903              : {
     904              :         UG_ASSERT(geo != nullptr, "Null pointer");
     905              :         UG_ASSERT(Velocity != nullptr, "Null pointer");
     906              : 
     907              :         //      \todo: think about: this should be something like scvf.num_sh()
     908              :         const size_t numSH = geo->num_sh();
     909              : 
     910              :         //      loop subcontrol volume faces
     911            0 :         for (size_t ip = 0; ip < geo->num_scvf(); ++ip)
     912              :         {
     913              :                 //      get subcontrol volume face
     914              :                 const typename TFVGeom::SCVF &scvf = geo->scvf(ip);
     915              : 
     916              :                 //      Compute flux
     917            0 :                 const number flux = VecDot(scvf.normal(), Velocity[ip]);
     918              : 
     919              :                 // Switch to no upwind in case of small velocity
     920            0 :                 if (VecTwoNorm(Velocity[ip]) < 1e-14)
     921              :                 {
     922              :                         // No upwind!
     923            0 :                         for (size_t sh = 0; sh < scvf.num_sh(); sh++)
     924            0 :                                 conv_shape(ip, sh) = flux * scvf.shape(sh);
     925              :                         for (size_t sh = scvf.num_sh(); sh < numSH; sh++)
     926              :                                 conv_shape(ip, sh) = 0.0;
     927            0 :                         if (computeDeriv)
     928              :                         {
     929            0 :                                 for (size_t sh = 0; sh < scvf.num_sh(); sh++)
     930              :                                         VecScale(D_vel(ip, sh), scvf.normal(), scvf.shape(sh));
     931              :                                 // temporary: case of hanging nodes
     932              :                                 for (size_t sh = scvf.num_sh(); sh < numSH; sh++)
     933              :                                         VecSet(D_vel(ip, sh), 0.0);
     934              :                         }
     935            0 :                         continue;
     936            0 :                 }
     937              : 
     938              :                 //      initialize shapes with zeroes
     939            0 :                 for (size_t sh = 0; sh < scvf.num_sh(); sh++)
     940            0 :                         conv_shape(ip, sh) = 0.0;
     941              : 
     942              :                 //  Hanging nodes
     943              :                 //      this is introduced here, hopefully temporarily: The problem is, that
     944              :                 //      for hanging nodes the number of shape function is not the number of
     945              :                 //      corners, but scvf.num_sh() currently returns the number of corners.
     946              :                 //      this is actually enough to interpolate the function, but still we
     947              :                 //      should reset the interpolation adding for hanging dofs to zero
     948              :                 for (size_t sh = scvf.num_sh(); sh < numSH; sh++)
     949              :                         conv_shape(ip, sh) = 0.0;
     950              : 
     951              :                 const MathVector<dim> *vCornerCoords = geo->corners();
     952            0 :                 size_t up = 0;
     953              :                 try
     954              :                 {
     955            0 :                         GetNodeNextToCut<typename TFVGeom::ref_elem_type, dim>(up, scvf.global_ip(), Velocity[ip], vCornerCoords);
     956              :                 }
     957            0 :                 UG_CATCH_THROW("Skewed upwind: Cannot find node next to cut");
     958              : 
     959            0 :                 conv_shape(ip, up) = flux;
     960              : 
     961              :                 //      Write Derivatives if wanted
     962            0 :                 if (computeDeriv)
     963              :                 {
     964            0 :                         for (size_t sh = 0; sh < numSH; ++sh)
     965              :                                 VecSet(D_vel(ip, sh), 0.0);
     966              :                         D_vel(ip, up) = scvf.normal();
     967              :                 }
     968              : 
     969              :                 //      The shapes do not depend of the diffusion tensor
     970              :         }
     971              : 
     972              :         //      we're done
     973            0 :         return true;
     974              : }
     975              : 
     976              : /////////////////////////////////////////////////////////////////////////////
     977              : // Linear Profile Skewed Upwind
     978              : /////////////////////////////////////////////////////////////////////////////
     979              : 
     980              : template <int TDim>
     981              : class ConvectionShapesLinearProfileSkewedUpwind
     982              :         : public IConvectionShapes<TDim>
     983              : {
     984              : public:
     985              :         ///     Base class
     986              :         typedef IConvectionShapes<TDim> base_type;
     987              : 
     988              :         ///     This class
     989              :         typedef ConvectionShapesLinearProfileSkewedUpwind<TDim> this_type;
     990              : 
     991              :         ///     Dimension
     992              :         static const int dim = TDim;
     993              : 
     994              : protected:
     995              :         //      explicitly forward some function
     996              :         using base_type::conv_shape;
     997              :         using base_type::conv_shape_diffusion;
     998              :         using base_type::D_vel;
     999              :         using base_type::non_zero_deriv_diffusion;
    1000              :         using base_type::register_update_func;
    1001              :         using base_type::set_non_zero_deriv_diffusion_flag;
    1002              : 
    1003              : public:
    1004              :         ///     constructor
    1005            0 :         ConvectionShapesLinearProfileSkewedUpwind()
    1006            0 :         {
    1007              :                 //      the shapes do not depend on the DiffDisp. Thus, we can set the
    1008              :                 //      derivative to be always zero w.r.t. the DiffDisp for all shapes
    1009              :                 set_non_zero_deriv_diffusion_flag(false);
    1010              : 
    1011              :                 //      register evaluation function
    1012              :                 boost::mpl::for_each<typename domain_traits<dim>::AllElemList>(RegisterElemFunc(this));
    1013              :                 boost::mpl::for_each<boost::mpl::range_c<int, 1, dim + 1>>(RegisterRefDimFunc(this));
    1014            0 :         }
    1015              : 
    1016              :         ///     update of values for FV geometry
    1017              :         template <typename TFVGeom>
    1018              :         bool update(const TFVGeom *geo,
    1019              :                                 const MathVector<dim> *Velocity,
    1020              :                                 const MathMatrix<dim, dim> *DiffDisp,
    1021              :                                 bool computeDeriv);
    1022              : 
    1023              : private:
    1024              :         ///     functor for registering the shapes for the element-templated FV geometries
    1025              :         struct RegisterElemFunc
    1026              :         {
    1027              :                 this_type *m_pThis;
    1028              :                 RegisterElemFunc(this_type *pThis) : m_pThis(pThis) {}
    1029              :                 template <typename TElem>
    1030              :                 void operator()(TElem &)
    1031              :                 {
    1032            0 :                         m_pThis->template register_func_for_elem_fvgeom<TElem, FV1Geometry<TElem, dim>>();
    1033              :                         //m_pThis->template register_func_for_elem_fvgeom< TElem, FV1CondensedGeometry<TElem, dim> >();
    1034              :                         //m_pThis->template register_func_for_elem_fvgeom< TElem, HFV1Geometry<TElem, dim> >();
    1035            0 :                 }
    1036              :         };
    1037              : 
    1038              :         /// registers the update function for an element type and a FV geometry
    1039              :         template <typename TElem, typename TFVGeom>
    1040              :         void register_func_for_elem_fvgeom()
    1041              :         {
    1042              :                 typedef bool (this_type::*TFunc)(const TFVGeom *, const MathVector<dim> *, const MathMatrix<dim, dim> *, bool);
    1043            0 :                 base_type::template register_update_func<TFVGeom, TFunc>(&this_type::template update<TFVGeom>);
    1044              :         }
    1045              : 
    1046              :         ///     functor for registering the shapes for the reference-dimension-templated FV geometries
    1047              :         struct RegisterRefDimFunc
    1048              :         {
    1049              :                 this_type *m_pThis;
    1050              :                 RegisterRefDimFunc(this_type *pThis) : m_pThis(pThis) {}
    1051              :                 template <typename TRefDim>
    1052              :                 void operator()(TRefDim &) { m_pThis->register_func_for_refDim<TRefDim::value>(); }
    1053              :         };
    1054              : 
    1055              :         /// registers the update function for a reference dimension
    1056              :         template <int refDim>
    1057              :         void register_func_for_refDim()
    1058              :         {
    1059              :                 //typedef DimFV1Geometry<refDim, dim> TGeom;
    1060              :                 //typedef bool (this_type::*TFunc) (const TGeom*, const MathVector<dim>*, const MathMatrix<dim, dim>*, bool);
    1061              :                 //base_type::template register_update_func<TGeom, TFunc>(&this_type::template update<TGeom>);
    1062              :         }
    1063              : };
    1064              : 
    1065              : template <int TDim>
    1066              : template <typename TFVGeom>
    1067            0 : bool ConvectionShapesLinearProfileSkewedUpwind<TDim>::
    1068              :         update(const TFVGeom *geo,
    1069              :                    const MathVector<dim> *Velocity,
    1070              :                    const MathMatrix<dim, dim> *DiffDisp,
    1071              :                    bool computeDeriv)
    1072              : {
    1073              :         UG_ASSERT(geo != nullptr, "Null pointer");
    1074              :         UG_ASSERT(Velocity != nullptr, "Null pointer");
    1075              : 
    1076              :         //      \todo: think about: this should be something like scvf.num_sh()
    1077              :         const size_t numSH = geo->num_sh();
    1078              : 
    1079              :         //      loop subcontrol volume faces
    1080            0 :         for (size_t ip = 0; ip < geo->num_scvf(); ++ip)
    1081              :         {
    1082              :                 //      get subcontrol volume face
    1083              :                 const typename TFVGeom::SCVF &scvf = geo->scvf(ip);
    1084              : 
    1085              :                 //      Compute flux
    1086            0 :                 const number flux = VecDot(scvf.normal(), Velocity[ip]);
    1087              : 
    1088              :                 // Switch to no upwind in case of small velocity
    1089            0 :                 if (VecTwoNorm(Velocity[ip]) < 1e-14)
    1090              :                 {
    1091              :                         // No upwind!
    1092            0 :                         for (size_t sh = 0; sh < scvf.num_sh(); sh++)
    1093            0 :                                 conv_shape(ip, sh) = flux * scvf.shape(sh);
    1094              :                         for (size_t sh = scvf.num_sh(); sh < numSH; sh++)
    1095              :                                 conv_shape(ip, sh) = 0.0;
    1096            0 :                         if (computeDeriv)
    1097              :                         {
    1098            0 :                                 for (size_t sh = 0; sh < scvf.num_sh(); sh++)
    1099              :                                         VecScale(D_vel(ip, sh), scvf.normal(), scvf.shape(sh));
    1100              :                                 // temporary, see above
    1101              :                                 for (size_t sh = scvf.num_sh(); sh < numSH; sh++)
    1102              :                                         VecSet(D_vel(ip, sh), 0.0);
    1103              :                         }
    1104            0 :                         continue;
    1105            0 :                 }
    1106              : 
    1107              :                 //      initialize shapes with zeroes
    1108            0 :                 for (size_t sh = 0; sh < scvf.num_sh(); sh++)
    1109            0 :                         conv_shape(ip, sh) = 0.0;
    1110              : 
    1111              :                 //  Hanging nodes
    1112              :                 //      this is introduced here, hopefully temporarily: The problem is, that
    1113              :                 //      for hanging nodes the number of shape function is not the number of
    1114              :                 //      corners, but scvf.num_sh() currently returns the number of corners.
    1115              :                 //      this is actually enough to interpolate the function, but still we
    1116              :                 //      should reset the interpolation adding for hanging dofs to zero
    1117              :                 for (size_t sh = scvf.num_sh(); sh < numSH; sh++)
    1118              :                         conv_shape(ip, sh) = 0.0;
    1119              : 
    1120              :                 const MathVector<dim> *vCornerCoords = geo->corners();
    1121              :                 // Reference element type
    1122              :                 typedef typename TFVGeom::ref_elem_type TRefElem;
    1123            0 :                 size_t side = 0;
    1124              :                 MathVector<dim> globalIntersection;
    1125              :                 MathVector<TRefElem::dim> localIntersection;
    1126              : 
    1127              :                 try
    1128              :                 {
    1129              :                         ElementSideRayIntersection<TRefElem, dim>(side, globalIntersection, localIntersection,
    1130              :                                                                                                           scvf.global_ip(), Velocity[ip], false /* search upwind */, vCornerCoords);
    1131              :                 }
    1132            0 :                 UG_CATCH_THROW("GetLinearProfileSkewedUpwindShapes: Cannot find cut side.");
    1133              : 
    1134              :                 //      get linear trial space
    1135              :                 static const ReferenceObjectID roid = TRefElem::REFERENCE_OBJECT_ID;
    1136              :                 const LocalShapeFunctionSet<TRefElem::dim> &TrialSpace =
    1137            0 :                         LocalFiniteElementProvider::get<TRefElem::dim>(roid, LFEID(LFEID::LAGRANGE, dim, 1));
    1138              : 
    1139              :                 //      get Reference Element
    1140            0 :                 static const TRefElem &rRefElem = Provider<TRefElem>::get();
    1141              : 
    1142              :         // Shape function values 
    1143              :                 std::vector<number> vShape;
    1144              :                 // Values of shape function gradients
    1145              :                 std::vector<MathVector<TRefElem::dim>> vShapeGrad;
    1146              :                 // Get values at the intersection point
    1147            0 :                 TrialSpace.shapes(vShape, localIntersection);
    1148            0 :                 TrialSpace.grads(vShapeGrad, localIntersection);
    1149              : 
    1150            0 :                 size_t num_corners_inters_side = rRefElem.num(dim - 1, side, 0);
    1151              : 
    1152              :                 //      loop corners of side
    1153            0 :                 for (size_t j = 0; j < num_corners_inters_side; ++j)
    1154              :                 {
    1155              :                         //      get corner
    1156            0 :                         const size_t co = rRefElem.id(dim-1, side, 0, j);
    1157              : 
    1158              :                         //      write shape
    1159            0 :                         conv_shape(ip, co) = flux * vShape[co];
    1160              :                 }
    1161              : 
    1162              :                 //      Write Derivatives if wanted
    1163              :                 if (computeDeriv)
    1164              :                 {
    1165              :                         // No derivatives yet!
    1166              :                 }
    1167              : 
    1168              :                 //      The shapes do not depend of the diffusion tensor
    1169              :         }
    1170              : 
    1171              :         //      we're done
    1172            0 :         return true;
    1173              : }
    1174              : 
    1175              : 
    1176              : } // end namespace ug
    1177              : 
    1178              : #endif /* __H__UG__LIB_DISC__SPATIAL_DISC__ELEM_DISC__DENSITY_DRIVEN_FLOW__FV1__CONV_SHAPE__ */
        

Generated by: LCOV version 2.0-1