LCOV - code coverage report
Current view: top level - ugbase/lib_disc/spatial_disc/disc_util - consistent_gravity.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 138 0
Test Date: 2026-09-22 09:15:05 Functions: 0.0 % 32 0

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2010-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__CONSISTENT_GRAVITY__
      34              : #define __H__UG__LIB_DISC__SPATIAL_DISC__ELEM_DISC__DENSITY_DRIVEN_FLOW__FV1__CONSISTENT_GRAVITY__
      35              : 
      36              : #include <vector>
      37              : 
      38              : // other ug4 modules
      39              : #include "common/common.h"
      40              : #include "lib_disc/reference_element/reference_mapping.h"
      41              : 
      42              : namespace ug{
      43              : 
      44              : /// Class for the computation of the standard version ('Voss-Souza-type') of the consistent gravity
      45              : /**
      46              :  * Density driven flow models involve the convection velocity depending on the
      47              :  * gradient of the pressure and the density-dependent gravity force, typically
      48              :  * of the form \f$\mathbf{v} = \mathbf{K} (- \nabla p + \rho \mathbf{g}) / \mu\f$,
      49              :  * where \f$\mathbf{K}\f$ is a matrix, \f$\mu\f$ a scalar, \f$\mathbf{g}\f$
      50              :  * gravity vector (all independent of \f$p\f$ or \f$\rho\f$), \f$p\f$ is
      51              :  * pressure, \f$rho\f$ is density (depending on the concentration, ...). (Both
      52              :  * the pressure and the concentration are unknown grid functions in the PDEs.)
      53              :  * Treating \f$p\f$ and \f$\rho\f$ as grid functions of the same class (like
      54              :  * the piecewise linear/bilinear interpolations of nodal values) leads to oscillatory
      55              :  * solutions because \f$\nabla p\f$ and \f$\rho \mathbf{g}\f$ belong to different
      56              :  * classes of grid functions. In particular, if \f$p\f$ is a piecewise linear
      57              :  * function, \f$\nabla p\f$ can never cancel the of the gravitaty force if 
      58              :  * \f$\rho\f$ increases linearly from the top down, although this happens in the
      59              :  * analytical solution. The idea of the consistent gravity is to consider a
      60              :  * vector function \f$\mathbf{h} = (h_x, h_y, \dots)\f$ that is in some sence a
      61              :  * primitive function for \f$\rho \mathbf{g}\f$ so that the velocity can be
      62              :  * written as \f$\mathbf{v} = - \mathbf{K} (p_x - h_x, p_y - h_y, \dots) / \mu\f$.
      63              :  * In the discretization, the function \f$\mathbf{h}\f$ should belong to the
      64              :  * same class of the grid functions as \f$p\f$. In the present implementation,
      65              :  * \f$\mathbf{h}\f$ is a piecewise linear/bilinear grid function.
      66              :  *
      67              :  * Class method 'prepare' computes the values of \f$h\f$ at the corners
      68              :  * of an element. Using these values, method 'compute' computes the
      69              :  * consistent gravity force \f$\rho \mathbf{g}\f$ (not \f$\mathbf{h}\f$!) at any
      70              :  * given point.
      71              :  *
      72              :  * \remark (Consistent gravity in the computation of the Jacobian)
      73              :  * The consistent gravity computed by the implemented methods depends linearly
      74              :  * on the density. Thus, to compute the derivative of the consistent gravity
      75              :  * w.r.t. the density at one of the corners of the element, set the density to
      76              :  * 1 at that corner and to 0 at all other corners, then call the functions. Then
      77              :  * 'prepare' prepares the nodal values of the derivatives and 'compute' computes
      78              :  * the derivative itself.
      79              :  *
      80              :  * Alternatively, you can set the density at that corner to the derivative
      81              :  * of the density w.r.t. the concentration (instead of 1). Then you get
      82              :  * directly the derivative of the consistent gravity w.r.t. the concentration
      83              :  * at that node.
      84              :  *
      85              :  * \remark There is an enhanced version of the consistent gravity. \see StdLinConsistentGravityX
      86              :  *
      87              :  * References:
      88              :  * <ul>
      89              :  *  <li> P. Frolkovic, P. Knabner, Consistent Velocity Approximations in Finite
      90              :  *       Element or Volume Discretizations of Density Driven Flow, In: Computational
      91              :  *       Methods in WaterResources XI, Vol. 1 (A.A. Aldama et al., eds.),
      92              :  *       Computational Mechanics Publication, Southhampten, 1996, p. 93-100
      93              :  *  </li>
      94              :  * </ul>
      95              :  *
      96              :  * \tparam refDim       dimensionality of the reference element (e.g. 2 for triangles, 3 for tetrahedra)
      97              :  */
      98              : template <int refDim>
      99              : class StdLinConsistentGravity
     100              : {
     101              : private:
     102              : //      static constants
     103              :         static const size_t _X_ = 0;
     104              :         static const size_t _Y_ = 1;
     105              :         static const size_t _Z_ = 2;
     106              :         
     107              : public:
     108              : 
     109              : ///     constructor (sets the 'not init.' flag)
     110            0 :         StdLinConsistentGravity () : m_nCo (0) {};
     111              : 
     112              : ///     computation of the primary function for the consistent gravity at corners, cf. the specializations
     113              :         template <int dim>
     114              :         inline void prepare
     115              :         (
     116              :                 MathVector<refDim>* vConsGravity, ///< where to save the values (n_co vectors)
     117              :                 const int n_co, ///< number of corners of the element
     118              :                 const MathVector<dim>* vCorners, ///< (global) coordinates of the corners (n_co vectors)
     119              :                 const number* vDensity, ///< corner density (n_co scalar values)
     120              :                 const MathVector<dim>& PhysicalGravity ///< the gravity vector
     121              :         )
     122              :         {
     123              :                 UG_THROW ("StdLinConsistentGravity: Combination of the world dim " << dim <<
     124              :                         "and the reference element dim " << refDim << " is not implemented.");
     125              :         }
     126              :         
     127              : ///     computation of the consistent gravity at a given point
     128              :         template <int dim>
     129            0 :         inline void compute
     130              :         (
     131              :                 MathVector<dim>& ConsistentGravity, ///< where to save the vector
     132              :                 const MathVector<refDim>& LocalCoord, ///< local coordinates of the point
     133              :                 const MathMatrix<dim, refDim>& JTInv, ///< inverse transposed Jacobian
     134              :                 const MathVector<refDim>* vLocalGrad, ///< gradients of the shape functions at the given point
     135              :                 const MathVector<refDim>* vConsGravity ///< primary function of the consistent gravity at corners
     136              :         )
     137              :         {
     138              :                 UG_ASSERT (m_nCo > 0, "StdLinConsistentGravity: Object not initialized.");
     139              :                 
     140              :                 MathVector<refDim> LocalGravity;
     141              :                 VecSet(LocalGravity, 0.0);
     142              :                 
     143              :         //      Loop shape functions
     144            0 :                 for(size_t sh = 0; sh < (size_t) m_nCo; sh++)
     145            0 :                         for(size_t d = 0; d < refDim; d++)
     146            0 :                                 LocalGravity[d] += vConsGravity[sh][d] * vLocalGrad[sh][d];
     147              : 
     148              :         //      Multiply by JacobianTransposedInverse
     149              :                 MatVecMult(ConsistentGravity, JTInv, LocalGravity);
     150            0 :         }
     151              :         
     152              : protected:
     153              :         
     154              :         int m_nCo; ///< number of corners of the element for which the object is init. (0 if not init)
     155              : 
     156              : ///     computation of the primary function for the consistent gravity at corners of an edge
     157              :         template <int dim>
     158            0 :         inline void prepare_edge
     159              :         (
     160              :                 MathVector<1>* vConsGravity, ///< where to save the values (2 vectors)
     161              :                 const MathVector<dim>* vCorners, ///< (global) coordinates of the corners (2 vectors)
     162              :                 const number* vDensity, ///< corner density (2 scalar values)
     163              :                 const MathVector<dim>& PhysicalGravity ///< the gravity vector
     164              :         )
     165              :         {
     166              :                 MathVector<1> LocalPoint;
     167              :                 MathVector<1> LocalGravity;
     168              :                 MathMatrix<1,dim> JT;
     169            0 :                 static ReferenceMapping<ReferenceEdge, dim> EdgeMapping;
     170              :                 EdgeMapping.update (vCorners);
     171              : 
     172              :                 /* compute the local gravity */
     173              :                 VecSet (LocalPoint, 0.0);
     174              :                 EdgeMapping.jacobian_transposed (JT, LocalPoint);
     175              :                 MatVecMult (LocalGravity, JT, PhysicalGravity);
     176              : 
     177            0 :                 vConsGravity[0][_X_] = 0.0;
     178            0 :                 vConsGravity[1][_X_] = LocalGravity[_X_]*(vDensity[0] + vDensity[1])*0.5;
     179            0 :         }
     180              :         
     181              : ///     computation of the primary function for the consistent gravity at corners of a triangle
     182              :         template <int dim>
     183            0 :         inline void prepare_triangle
     184              :         (
     185              :                 MathVector<2>* vConsGravity, ///< where to save the values (3 vectors)
     186              :                 const MathVector<dim>* vCorners, ///< (global) coordinates of the corners (3 vectors)
     187              :                 const number* vDensity, ///< corner density (3 scalar values)
     188              :                 const MathVector<dim>& PhysicalGravity ///< the gravity vector
     189              :         )
     190              :         {
     191              :                 MathVector<2> LocalPoint;
     192              :                 MathVector<2> LocalGravity;
     193              :                 MathMatrix<2,dim> JT;
     194            0 :                 static ReferenceMapping<ReferenceTriangle, dim> TriangleMapping;
     195            0 :                 TriangleMapping.update (vCorners);
     196              : 
     197              :                 /* compute the local gravity */
     198              :                 VecSet (LocalPoint, 0.0);
     199              :                 TriangleMapping.jacobian_transposed (JT, LocalPoint);
     200              :                 MatVecMult (LocalGravity, JT, PhysicalGravity);
     201              : 
     202            0 :                 vConsGravity[0][_X_] = 0.0; vConsGravity[2][_X_] = 0.0;
     203            0 :                 vConsGravity[1][_X_] = LocalGravity[_X_]*(vDensity[0] + vDensity[1])*0.5;
     204              : 
     205            0 :                 vConsGravity[0][_Y_] = 0.0; vConsGravity[1][_Y_] = 0.0;
     206            0 :                 vConsGravity[2][_Y_] = LocalGravity[_Y_]*(vDensity[0] + vDensity[2])*0.5;
     207            0 :         }
     208              : 
     209              : ///     computation of the primary function for the consistent gravity at corners of a quadrilateral
     210              :         template <int dim>
     211            0 :         inline void prepare_quadrilateral
     212              :         (
     213              :                 MathVector<2>* vConsGravity, ///< where to save the values (4 vectors)
     214              :                 const MathVector<dim>* vCorners, ///< (global) coordinates of the corners (4 vectors)
     215              :                 const number* vDensity, ///< corner density (4 scalar values)
     216              :                 const MathVector<dim>& PhysicalGravity ///< the gravity vector
     217              :         )
     218              :         {
     219              :                 MathVector<2> LocalPoint;
     220              :                 MathVector<2> LocalGravityAt000, LocalGravityAt110;
     221              :                 MathMatrix<2,dim> JT;
     222            0 :                 static ReferenceMapping<ReferenceQuadrilateral, dim> QuadMapping;
     223              :                 QuadMapping.update (vCorners);
     224              : 
     225              :                 /* compute the local gravity at local corner (0,0) */
     226              :                 VecSet (LocalPoint, 0.0);
     227            0 :                 QuadMapping.jacobian_transposed (JT, LocalPoint);
     228              :                 MatVecMult (LocalGravityAt000, JT, PhysicalGravity);
     229              : 
     230              :                 /* compute the local gravity at local corner (1,1) */
     231              :                 VecSet (LocalPoint, 1.0);
     232            0 :                 QuadMapping.jacobian_transposed (JT, LocalPoint);
     233              :                 MatVecMult (LocalGravityAt110, JT, PhysicalGravity);
     234              : 
     235            0 :                 vConsGravity[0][_X_] = 0.0; vConsGravity[3][_X_] = 0.0;
     236            0 :                 vConsGravity[1][_X_] = LocalGravityAt000[_X_]*(vDensity[0] + vDensity[1])*0.5;
     237            0 :                 vConsGravity[2][_X_] = LocalGravityAt110[_X_]*(vDensity[2] + vDensity[3])*0.5;
     238              : 
     239            0 :                 vConsGravity[0][_Y_] = 0.0; vConsGravity[1][_Y_] = 0.0;
     240            0 :                 vConsGravity[2][_Y_] = LocalGravityAt110[_Y_]*(vDensity[1] + vDensity[2])*0.5;
     241            0 :                 vConsGravity[3][_Y_] = LocalGravityAt000[_Y_]*(vDensity[0] + vDensity[3])*0.5;
     242            0 :         }
     243              :         
     244              : ///     computation of the primary function for the consistent gravity at corners of a tetrahedron
     245              :         template <int dim>
     246            0 :         inline void prepare_tetrahedron
     247              :         (
     248              :                 MathVector<3>* vConsGravity, ///< where to save the values (4 vectors)
     249              :                 const MathVector<dim>* vCorners, ///< (global) coordinates of the corners (4 vectors)
     250              :                 const number* vDensity, ///< corner density (4 scalar values)
     251              :                 const MathVector<dim>& PhysicalGravity ///< the gravity vector
     252              :         )
     253              :         {
     254              :                 MathVector<3> LocalPoint;
     255              :                 MathVector<3> LocalGravity;
     256              :                 MathMatrix<3,dim> JT;
     257            0 :                 static ReferenceMapping<ReferenceTetrahedron, dim> TetMapping;
     258            0 :                 TetMapping.update (vCorners);
     259              : 
     260              :                 /* compute the local gravity */
     261            0 :                 LocalPoint.x() = 0.0; LocalPoint.y() = 0.0; LocalPoint.z() = 0.0;
     262            0 :                 TetMapping.jacobian_transposed (JT, LocalPoint);
     263              :                 MatVecMult (LocalGravity, JT, PhysicalGravity);
     264              : 
     265            0 :                 vConsGravity[0][_X_] = 0.0; vConsGravity[2][_X_] = 0.0; vConsGravity[3][_X_] = 0.0;
     266            0 :                 vConsGravity[1][_X_] = LocalGravity[_X_]*(vDensity[0] + vDensity[1])*0.5;
     267              : 
     268            0 :                 vConsGravity[0][_Y_] = 0.0; vConsGravity[1][_Y_] = 0.0; vConsGravity[3][_Y_] = 0.0;
     269            0 :                 vConsGravity[2][_Y_] = LocalGravity[_Y_]*(vDensity[0] + vDensity[2])*0.5;
     270              : 
     271            0 :                 vConsGravity[0][_Z_] = 0.0; vConsGravity[1][_Z_] = 0.0; vConsGravity[2][_Z_] = 0.0;
     272            0 :                 vConsGravity[3][_Z_] = LocalGravity[_Z_]*(vDensity[0] + vDensity[3])*0.5;
     273            0 :         }
     274              :         
     275              : ///     computation of the primary function for the consistent gravity at corners of a pyramid
     276              : /**
     277              :  * TODO: Verify this implementation! Cf. UG3.
     278              :  */
     279              :         template <int dim>
     280            0 :         inline void prepare_pyramid
     281              :         (
     282              :                 MathVector<3>* vConsGravity, ///< where to save the values (5 vectors)
     283              :                 const MathVector<dim>* vCorners, ///< (global) coordinates of the corners (5 vectors)
     284              :                 const number* vDensity, ///< corner density (5 scalar values)
     285              :                 const MathVector<dim>& PhysicalGravity ///< the gravity vector
     286              :         )
     287              :         {
     288              :                 MathVector<3> LocalPoint;
     289              :                 MathVector<3> LocalGravityAt000, LocalGravityAt110;
     290              :                 MathMatrix<3,dim> JT;
     291            0 :                 static ReferenceMapping<ReferencePyramid, dim> PyramidMapping;
     292              :                 PyramidMapping.update (vCorners);
     293              : 
     294              :                 /* compute the local gravity at local corner (0,0,0) */
     295            0 :                 LocalPoint.x() = 0.0; LocalPoint.y() = 0.0; LocalPoint.z() = 0.0;
     296            0 :                 PyramidMapping.jacobian_transposed (JT, LocalPoint);
     297              :                 MatVecMult (LocalGravityAt000, JT, PhysicalGravity);
     298              : 
     299              :                 /* compute the local gravity at local corner (1,1,0) */
     300            0 :                 LocalPoint.x() = 1.0; LocalPoint.y() = 1.0; LocalPoint.z() = 0.0;
     301            0 :                 PyramidMapping.jacobian_transposed (JT, LocalPoint);
     302              :                 MatVecMult (LocalGravityAt110, JT, PhysicalGravity);
     303              : 
     304            0 :                 vConsGravity[0][_X_] = 0.0; vConsGravity[3][_X_] = 0.0; vConsGravity[4][_X_] = 0.0;
     305            0 :                 vConsGravity[1][_X_] = LocalGravityAt000[_X_]*(vDensity[0] + vDensity[1])*0.5;
     306            0 :                 vConsGravity[2][_X_] = LocalGravityAt110[_X_]*(vDensity[2] + vDensity[3])*0.5;
     307              : 
     308            0 :                 vConsGravity[0][_Y_] = 0.0; vConsGravity[1][_Y_] = 0.0; vConsGravity[4][_Y_] = 0.0;
     309            0 :                 vConsGravity[2][_Y_] = LocalGravityAt110[_Y_]*(vDensity[1] + vDensity[2])*0.5;
     310            0 :                 vConsGravity[3][_Y_] = LocalGravityAt000[_Y_]*(vDensity[0] + vDensity[3])*0.5;
     311              : 
     312            0 :                 vConsGravity[0][_Z_] = 0.0; vConsGravity[1][_Z_] = 0.0;
     313            0 :                 vConsGravity[2][_Z_] = 0.0; vConsGravity[3][_Z_] = 0.0;
     314            0 :                 vConsGravity[4][_Z_] = LocalGravityAt000[_Z_]*(vDensity[0] + vDensity[4])*0.5;
     315            0 :         }
     316              :         
     317              : ///     computation of the primary function for the consistent gravity at corners of a prism
     318              :         template <int dim>
     319            0 :         inline void prepare_prism
     320              :         (
     321              :                 MathVector<3>* vConsGravity, ///< where to save the values (6 vectors)
     322              :                 const MathVector<dim>* vCorners, ///< (global) coordinates of the corners (6 vectors)
     323              :                 const number* vDensity, ///< corner density (6 scalar values)
     324              :                 const MathVector<dim>& PhysicalGravity ///< the gravity vector
     325              :         )
     326              :         {
     327              :                 MathVector<3> LocalPoint;
     328              :                 MathVector<3> LocalGravityAt000, LocalGravityAt101, LocalGravityAt011;
     329              :                 MathMatrix<3,dim> JT;
     330            0 :                 static ReferenceMapping<ReferencePrism, dim> PrismMapping;
     331              :                 PrismMapping.update (vCorners);
     332              : 
     333              :                 /* compute the local gravity at local corner (0,0,0) */
     334            0 :                 LocalPoint.x() = 0.0; LocalPoint.y() = 0.0; LocalPoint.z() = 0.0;
     335            0 :                 PrismMapping.jacobian_transposed (JT, LocalPoint);
     336              :                 MatVecMult (LocalGravityAt000, JT, PhysicalGravity);
     337              : 
     338              :                 /* compute the local gravity at local corner (1,0,1) */
     339            0 :                 LocalPoint.x() = 1.0; LocalPoint.y() = 0.0; LocalPoint.z() = 1.0;
     340            0 :                 PrismMapping.jacobian_transposed (JT, LocalPoint);
     341              :                 MatVecMult (LocalGravityAt101, JT, PhysicalGravity);
     342              : 
     343              :                 /* compute the local gravity at local corner (0,1,1) */
     344            0 :                 LocalPoint.x() = 0.0; LocalPoint.y() = 1.0; LocalPoint.z() = 1.0;
     345            0 :                 PrismMapping.jacobian_transposed (JT, LocalPoint);
     346              :                 MatVecMult (LocalGravityAt011, JT, PhysicalGravity);
     347              : 
     348            0 :                 vConsGravity[0][_X_] = 0.0; vConsGravity[2][_X_] = 0.0;
     349            0 :                 vConsGravity[3][_X_] = 0.0; vConsGravity[5][_X_] = 0.0;
     350            0 :                 vConsGravity[1][_X_] = LocalGravityAt000[_X_]*(vDensity[0] + vDensity[1])*0.5;
     351            0 :                 vConsGravity[4][_X_] = LocalGravityAt011[_X_]*(vDensity[3] + vDensity[4])*0.5;
     352              : 
     353            0 :                 vConsGravity[0][_Y_] = 0.0; vConsGravity[1][_Y_] = 0.0;
     354            0 :                 vConsGravity[3][_Y_] = 0.0; vConsGravity[4][_Y_] = 0.0;
     355            0 :                 vConsGravity[2][_Y_] = LocalGravityAt000[_Y_]*(vDensity[0] + vDensity[2])*0.5;
     356            0 :                 vConsGravity[5][_Y_] = LocalGravityAt011[_Y_]*(vDensity[3] + vDensity[5])*0.5;
     357              : 
     358            0 :                 vConsGravity[0][_Z_] = 0.0; vConsGravity[1][_Z_] = 0.0; vConsGravity[2][_Z_] = 0.0;
     359            0 :                 vConsGravity[3][_Z_] = LocalGravityAt000[_Z_]*(vDensity[0] + vDensity[3])*0.5;
     360            0 :                 vConsGravity[4][_Z_] = LocalGravityAt101[_Z_]*(vDensity[1] + vDensity[4])*0.5;
     361            0 :                 vConsGravity[5][_Z_] = LocalGravityAt011[_Z_]*(vDensity[2] + vDensity[5])*0.5;
     362            0 :         }
     363              :         
     364              : ///     computation of the primary function for the consistent gravity at corners of a hexahedron
     365              :         template <int dim>
     366            0 :         inline void prepare_hexahedron
     367              :         (
     368              :                 MathVector<3>* vConsGravity, ///< where to save the values (8 vectors)
     369              :                 const MathVector<dim>* vCorners, ///< (global) coordinates of the corners (8 vectors)
     370              :                 const number* vDensity, ///< corner density (8 scalar values)
     371              :                 const MathVector<dim>& PhysicalGravity ///< the gravity vector
     372              :         )
     373              :         {
     374              :                 MathVector<3> LocalPoint;
     375              :                 MathVector<3> LocalGravityAt000, LocalGravityAt110, LocalGravityAt101, LocalGravityAt011;
     376              :                 MathMatrix<3,dim> JT;
     377            0 :                 static ReferenceMapping<ReferenceHexahedron, dim> HexMapping;
     378              :                 HexMapping.update (vCorners);
     379              : 
     380              :                 /* compute the local gravity at local corner (0,0,0) */
     381            0 :                 LocalPoint.x() = 0.0; LocalPoint.y() = 0.0; LocalPoint.z() = 0.0;
     382            0 :                 HexMapping.jacobian_transposed (JT, LocalPoint);
     383              :                 MatVecMult (LocalGravityAt000, JT, PhysicalGravity);
     384              : 
     385              :                 /* compute the local gravity at local corner (1,1,0) */
     386            0 :                 LocalPoint.x() = 1.0; LocalPoint.y() = 1.0; LocalPoint.z() = 0.0;
     387            0 :                 HexMapping.jacobian_transposed (JT, LocalPoint);
     388              :                 MatVecMult (LocalGravityAt110, JT, PhysicalGravity);
     389              : 
     390              :                 /* compute the local gravity at local corner (1,0,1) */
     391            0 :                 LocalPoint.x() = 1.0; LocalPoint.y() = 0.0; LocalPoint.z() = 1.0;
     392            0 :                 HexMapping.jacobian_transposed (JT, LocalPoint);
     393              :                 MatVecMult (LocalGravityAt101, JT, PhysicalGravity);
     394              : 
     395              :                 /* compute the local gravity at local corner (0,1,1) */
     396            0 :                 LocalPoint.x() = 0.0; LocalPoint.y() = 1.0; LocalPoint.z() = 1.0;
     397            0 :                 HexMapping.jacobian_transposed (JT, LocalPoint);
     398              :                 MatVecMult (LocalGravityAt011, JT, PhysicalGravity);
     399              : 
     400            0 :                 vConsGravity[0][_X_] = 0.0; vConsGravity[3][_X_] = 0.0;
     401            0 :                 vConsGravity[4][_X_] = 0.0; vConsGravity[7][_X_] = 0.0;
     402            0 :                 vConsGravity[1][_X_] = LocalGravityAt000[_X_]*(vDensity[0] + vDensity[1])*0.5;
     403            0 :                 vConsGravity[2][_X_] = LocalGravityAt110[_X_]*(vDensity[2] + vDensity[3])*0.5;
     404            0 :                 vConsGravity[5][_X_] = LocalGravityAt101[_X_]*(vDensity[4] + vDensity[5])*0.5;
     405            0 :                 vConsGravity[6][_X_] = LocalGravityAt011[_X_]*(vDensity[6] + vDensity[7])*0.5;
     406              : 
     407            0 :                 vConsGravity[0][_Y_] = 0.0; vConsGravity[1][_Y_] = 0.0;
     408            0 :                 vConsGravity[4][_Y_] = 0.0; vConsGravity[5][_Y_] = 0.0;
     409            0 :                 vConsGravity[2][_Y_] = LocalGravityAt110[_Y_]*(vDensity[1] + vDensity[2])*0.5;
     410            0 :                 vConsGravity[3][_Y_] = LocalGravityAt000[_Y_]*(vDensity[0] + vDensity[3])*0.5;
     411            0 :                 vConsGravity[6][_Y_] = LocalGravityAt101[_Y_]*(vDensity[5] + vDensity[6])*0.5;
     412            0 :                 vConsGravity[7][_Y_] = LocalGravityAt011[_Y_]*(vDensity[4] + vDensity[7])*0.5;
     413              : 
     414            0 :                 vConsGravity[0][_Z_] = 0.0; vConsGravity[1][_Z_] = 0.0;
     415            0 :                 vConsGravity[2][_Z_] = 0.0; vConsGravity[3][_Z_] = 0.0;
     416            0 :                 vConsGravity[4][_Z_] = LocalGravityAt000[_Z_]*(vDensity[0] + vDensity[4])*0.5;
     417            0 :                 vConsGravity[5][_Z_] = LocalGravityAt101[_Z_]*(vDensity[1] + vDensity[5])*0.5;
     418            0 :                 vConsGravity[6][_Z_] = LocalGravityAt110[_Z_]*(vDensity[2] + vDensity[6])*0.5;
     419            0 :                 vConsGravity[7][_Z_] = LocalGravityAt011[_Z_]*(vDensity[3] + vDensity[7])*0.5;
     420            0 :         }
     421              : };
     422              : 
     423              : /// spacialization of the method for edges (reference dimension 1)
     424              : template <>
     425              : template <int dim>
     426              : void StdLinConsistentGravity<1>::prepare
     427              : (
     428              :         MathVector<1>* vConsGravity, ///< where to save the values (n_co vectors)
     429              :         const int n_co, ///< number of corners of the element (should be 2)
     430              :         const MathVector<dim>* vCorners, ///< (global) coordinates of the corners (n_co vectors)
     431              :         const number* vDensity, ///< corner density (n_co scalar values)
     432              :         const MathVector<dim>& PhysicalGravity ///< the gravity vector
     433              : )
     434              : {
     435              :         UG_ASSERT (n_co == 2, "StdLinConsistentGravity: Illegal number of corners of an edge.");
     436            0 :         m_nCo = n_co;
     437            0 :         this->template prepare_edge<dim> (vConsGravity, vCorners, vDensity, PhysicalGravity);
     438              : }
     439              : 
     440              : /// spacialization of the method for faces (reference dimension 2)
     441              : template <>
     442              : template <int dim>
     443            0 : void StdLinConsistentGravity<2>::prepare
     444              : (
     445              :         MathVector<2>* vConsGravity, ///< where to save the values (n_co vectors)
     446              :         const int n_co, ///< number of corners of the element
     447              :         const MathVector<dim>* vCorners, ///< (global) coordinates of the corners (n_co vectors)
     448              :         const number* vDensity, ///< corner density (n_co scalar values)
     449              :         const MathVector<dim>& PhysicalGravity ///< the gravity vector
     450              : )
     451              : {
     452            0 :         switch (m_nCo = n_co)
     453              :         {
     454            0 :                 case 3:
     455            0 :                         this->template prepare_triangle<dim> (vConsGravity, vCorners, vDensity, PhysicalGravity);
     456            0 :                         break;
     457            0 :                 case 4:
     458            0 :                         this->template prepare_quadrilateral<dim> (vConsGravity, vCorners, vDensity, PhysicalGravity);
     459            0 :                         break;
     460            0 :                 default:
     461            0 :                         UG_THROW ("StdLinConsistentGravity: Illegal number of corners ("
     462              :                                 << n_co << ") of an element with reference dimension 2.");
     463              :         }
     464            0 : }
     465              : 
     466              : /// spacialization of the method for volumes (reference dimension 3)
     467              : template <>
     468              : template <int dim>
     469            0 : void StdLinConsistentGravity<3>::prepare
     470              : (
     471              :         MathVector<3>* vConsGravity, ///< where to save the values (n_co vectors)
     472              :         const int n_co, ///< number of corners of the element
     473              :         const MathVector<dim>* vCorners, ///< (global) coordinates of the corners (n_co vectors)
     474              :         const number* vDensity, ///< corner density (n_co scalar values)
     475              :         const MathVector<dim>& PhysicalGravity ///< the gravity vector
     476              : )
     477              : {
     478            0 :         switch (m_nCo = n_co)
     479              :         {
     480            0 :                 case 4:
     481            0 :                         this->template prepare_tetrahedron<dim> (vConsGravity, vCorners, vDensity, PhysicalGravity);
     482            0 :                         break;
     483            0 :                 case 5:
     484            0 :                         this->template prepare_pyramid<dim> (vConsGravity, vCorners, vDensity, PhysicalGravity);
     485            0 :                         break;
     486            0 :                 case 6:
     487            0 :                         this->template prepare_prism<dim> (vConsGravity, vCorners, vDensity, PhysicalGravity);
     488            0 :                         break;
     489            0 :                 case 8:
     490            0 :                         this->template prepare_hexahedron<dim> (vConsGravity, vCorners, vDensity, PhysicalGravity);
     491            0 :                         break;
     492            0 :                 default:
     493            0 :                         UG_THROW ("StdLinConsistentGravity: Illegal number of corners ("
     494              :                                 << n_co << ") of an element with reference dimension 3.");
     495              :         }
     496            0 : }
     497              : 
     498              : /// Class for the computation of the enhanced version ('Frolkovic-type') of the consistent gravity
     499              : /**
     500              :  * Implementation of the enhanced ('Frolkovic-type') version of the consistent
     501              :  * gravity for simplices (triangles and tetrahedra) in the case of the gravity
     502              :  * force parallel to the z-axis. For all other elements and other gravities,
     503              :  * the same method as in StdLinConsistentGravity is used.
     504              :  * \see StdLinConsistentGravity
     505              :  *
     506              :  * References:
     507              :  * <ul>
     508              :  *  <li> P. Frolkovic, Consistent velocity approximation for density driven
     509              :  *       flow and transport, In: Advanced Computational Methods in Engineering,
     510              :  *       Part 2: Contributed papers; (R. Van Keer at al., eds.), Shaker Publishing,
     511              :  *       Maastricht, 1998, p. 603-611
     512              :  *  </li>
     513              :  * </ul>
     514              :  *
     515              :  * \tparam refDim       dimensionality of the reference element (e.g. 2 for triangles, 3 for tetrahedra)
     516              :  */
     517              : template <int refDim>
     518              : class StdLinConsistentGravityX : public StdLinConsistentGravity<refDim>
     519              : {
     520              :         typedef StdLinConsistentGravity<refDim> base_type;
     521              :         
     522              : public:
     523              : 
     524              : ///     constructor
     525              :         StdLinConsistentGravityX () {}
     526              :         
     527              : ///     computation of the primary function for the consistent gravity at corners, cf. the specializations
     528              :         template <int dim>
     529              :         inline void prepare
     530              :         (
     531              :                 MathVector<refDim>* vConsGravity, ///< where to save the values (n_co vectors)
     532              :                 const int n_co, ///< number of corners of the element
     533              :                 const MathVector<dim>* vCorners, ///< (global) coordinates of the corners (n_co vectors)
     534              :                 const number* vDensity, ///< corner density (n_co scalar values)
     535              :                 const MathVector<dim>& PhysicalGravity ///< the gravity vector
     536              :         )
     537              :         {
     538              :                 base_type::template prepare<dim>
     539              :                         (vConsGravity, n_co, vCorners, vDensity, PhysicalGravity);
     540              :                 // C.f. the specializations below for the enhanced version
     541              :         }
     542              :         
     543              : ///     computation of the consistent gravity at a given point
     544              :         template <int dim>
     545              :         inline void compute
     546              :         (
     547              :                 MathVector<dim>& ConsistentGravity, ///< where to save the vector
     548              :                 const MathVector<refDim>& LocalCoord, ///< local coordinates of the point
     549              :                 const MathMatrix<dim, refDim>& JTInv, ///< inverse transposed Jacobian
     550              :                 const MathVector<refDim>* vLocalGrad, ///< gradients of the shape functions at the given point
     551              :                 const MathVector<refDim>* vConsGravity ///< primary function of the consistent gravity at corners
     552              :         )
     553              :         {
     554              :                 if (base_type::m_nCo > 0) // use the standard version
     555              :                         base_type::template compute<dim> (ConsistentGravity, LocalCoord, JTInv, vLocalGrad, vConsGravity);
     556              :                 else
     557              :                 {
     558              :                 //      special method for triangles and tetrahedra, currently only in the full dimension
     559              :                         UG_ASSERT (dim == refDim && base_type::m_nCo == -(refDim+1), "StdLinConsistentGravityX: Illegal initialization of the object.");
     560              :                 
     561              :                         MathVector<refDim> LocalGravity;
     562              :                         VecSet (LocalGravity, 0.0);
     563              :                         
     564              :                         for (size_t d = 0; d < refDim; d++)
     565              :                                 LocalGravity[d] = vConsGravity[d+1][dim-1];
     566              :         
     567              :                         //      multiply by JacobianTransposedInverse
     568              :                         MatVecMult(ConsistentGravity, JTInv, LocalGravity);
     569              :                         
     570              :                         //      correct the first coordinates
     571              :                         for (size_t d = 0; d < dim-1; d++)
     572              :                                 for (size_t sh = 1; sh <= refDim; sh++)
     573              :                                         ConsistentGravity[d] -= vConsGravity[sh][d] * LocalCoord[sh-1];
     574              :                 }
     575              :         }
     576              :         
     577              : protected:
     578              :         
     579              : ///     computation of the extended version of the corner consistent gravity for simplices (only in full dimension!)
     580              :         template <typename refElem, int dim>
     581              :         inline void prepare_simplex
     582              :         (
     583              :                 MathVector<refDim>* vConsGravity, ///< where to save the values (dim+1 vectors)
     584              :                 const MathVector<dim>* vCorners, ///< (global) coordinates of the corners (dim+1 vectors)
     585              :                 const number* vDensity, ///< corner density (dim+1 scalar values)
     586              :                 const MathVector<dim>& PhysicalGravity ///< the gravity vector (MUST BE (0, ..., 0, g))
     587              :         )
     588              :         {
     589              :                 number DensityIP, Diff, gradient;
     590              :                 MathVector<refDim> LocalPoint;
     591              :                 MathVector<dim> ShiftedGlobalPoint;
     592              :                 MathMatrix<refDim,dim> JT;
     593              :                 static ReferenceMapping<refElem, dim> Mapping;
     594              :                 Mapping.update (vCorners);
     595              :                 Mapping.jacobian_transposed_inverse (JT, vCorners[0]); // the 2. argument is dummy
     596              : 
     597              :                 for (size_t i = 1; i < dim+1; i++)
     598              :                 {
     599              :                         VecSubtract (ShiftedGlobalPoint, vCorners[i], vCorners[0]);
     600              :                         Diff = ShiftedGlobalPoint [dim-1];
     601              : 
     602              :                         ShiftedGlobalPoint [dim-1] = 0.0;
     603              :                         TransposedMatVecMult (LocalPoint, JT, ShiftedGlobalPoint);
     604              :                         
     605              :                         DensityIP = 1;
     606              :                         for (size_t j = 0; j < dim; j++) DensityIP -= LocalPoint[j]; //GN(0)=1-local(0)-local(1)-...
     607              :                         DensityIP *= vDensity[0];
     608              :                         for (size_t j = 1; j < dim+1; j++)
     609              :                                 DensityIP += vDensity[j] * LocalPoint[j-1]; //GN(j)=local(j-1) for j=1,2,...
     610              :                         
     611              :                         for(size_t j = 0; j < dim-1; ++j)
     612              :                         {
     613              :                                 gradient = 0.0;
     614              :                                 for (size_t k = 0; k < dim; k++)
     615              :                                         gradient += JT[j][k] * (vDensity[k+1] - vDensity[0]);
     616              :                                 vConsGravity[i][j] = Diff * PhysicalGravity[dim-1] * gradient;
     617              :                         }
     618              :                         vConsGravity[i][dim-1] = Diff * PhysicalGravity[dim-1] * (vDensity[i] + DensityIP)*0.5;
     619              :                 }
     620              :         }
     621              : };
     622              : 
     623              : /// spacialization of the method for faces (reference dimension 2)
     624              : template <>
     625              : template <int dim>
     626              : void StdLinConsistentGravityX<2>::prepare
     627              : (
     628              :         MathVector<2>* vConsGravity, ///< where to save the values (n_co vectors)
     629              :         const int n_co, ///< number of corners of the element
     630              :         const MathVector<dim>* vCorners, ///< (global) coordinates of the corners (n_co vectors)
     631              :         const number* vDensity, ///< corner density (n_co scalar values)
     632              :         const MathVector<dim>& PhysicalGravity ///< the gravity vector
     633              : )
     634              : {
     635              :         if (dim == 2 && n_co == 3 && PhysicalGravity[0] == 0.0) // use the enhanced version
     636              :         {
     637              :                 m_nCo = -3;
     638              :                 this->template prepare_simplex<ReferenceTriangle, dim>
     639              :                         (vConsGravity, vCorners, vDensity, PhysicalGravity);
     640              :         }
     641              :         else // use the standard version
     642              :                 base_type::template prepare<dim>
     643              :                         (vConsGravity, n_co, vCorners, vDensity, PhysicalGravity);
     644              : }
     645              : 
     646              : /// spacialization of the method for volumes (reference dimension 3)
     647              : template <>
     648              : template <int dim>
     649              : void StdLinConsistentGravityX<3>::prepare
     650              : (
     651              :         MathVector<3>* vConsGravity, ///< where to save the values (n_co vectors)
     652              :         const int n_co, ///< number of corners of the element
     653              :         const MathVector<dim>* vCorners, ///< (global) coordinates of the corners (n_co vectors)
     654              :         const number* vDensity, ///< corner density (n_co scalar values)
     655              :         const MathVector<dim>& PhysicalGravity ///< the gravity vector
     656              : )
     657              : {
     658              :         if (dim == 3 && n_co == 4 && PhysicalGravity[0] == 0.0 && PhysicalGravity[1] == 0.0) // use the enhanced version
     659              :         {
     660              :                 m_nCo = -4;
     661              :                 this->template prepare_simplex<ReferenceTetrahedron, dim>
     662              :                         (vConsGravity, vCorners, vDensity, PhysicalGravity);
     663              :         }
     664              :         else // use the standard version
     665              :                 base_type::template prepare<dim>
     666              :                         (vConsGravity, n_co, vCorners, vDensity, PhysicalGravity);
     667              : }
     668              : 
     669              : } // end namespace ug
     670              : 
     671              : #endif /* __H__UG__LIB_DISC__SPATIAL_DISC__ELEM_DISC__DENSITY_DRIVEN_FLOW__FV1__CONSISTENT_GRAVITY__ */
        

Generated by: LCOV version 2.0-1