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

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2026:  CEMSE, KAUST
       3              :  * Author: Dmitry Logashenko
       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__CONSISTENT_GRAVITY_LINKER__
      34              : #define __H__UG__LIB_DISC__SPATIAL_DISC__CONSISTENT_GRAVITY_LINKER__
      35              : 
      36              : #include <vector>
      37              : 
      38              : #include "lib_disc/local_finite_element/local_finite_element_provider.h"
      39              : #include "lib_disc/spatial_disc/disc_util/consistent_gravity.h"
      40              : #include "linker.h"
      41              : #ifdef UG_FOR_LUA
      42              : #include "bindings/lua/lua_user_data.h"
      43              : #endif
      44              : 
      45              : namespace ug{
      46              : 
      47              : 
      48              : ////////////////////////////////////////////////////////////////////////////////
      49              : // Consistent Gravity linker
      50              : ////////////////////////////////////////////////////////////////////////////////
      51              : 
      52              : /// Linker for the consistent gravity (according to P. Frolkovic)
      53              : /**
      54              :  * This linker computes the s.c. consistent gravity \f$[ \rho \mathbf{g}  ]_{consistent} \f$, according to Frolkovic,
      55              :  * where
      56              :  * <ul>
      57              :  * <li> \f$ \rho \f$    the density
      58              :  * <li> \f$ \mathbf{g} \f$  constant gravity
      59              :  * </ul>
      60              :  * is the input parameter. ( \f$ \mathbf{g} \f$ should be constant.)
      61              :  *
      62              :  * References:
      63              :  * <ul>
      64              :  *  <li> P. Frolkovic, P. Knabner, Consistent Velocity Approximations in Finite
      65              :  *       Element or Volume Discretizations of Density Driven Flow, In: Computational
      66              :  *       Methods in WaterResources XI, Vol. 1 (A.A. Aldama et al., eds.),
      67              :  *       Computational Mechanics Publication, Southhampten, 1996, p. 93-100
      68              :  *  </li>
      69              :  * </ul>
      70              :  */
      71              : template <int dim>
      72              : class ConsistentGravityLinker
      73              :         : public StdDataLinker<ConsistentGravityLinker<dim>, MathVector<dim>, dim>
      74              : {
      75              :         ///     Base class type
      76              :                 typedef StdDataLinker<ConsistentGravityLinker<dim>, MathVector<dim>, dim> base_type;
      77              :         
      78              :         /// The world dimension
      79              :                 static const int world_dim = dim;
      80              :                 
      81              :         public:
      82            0 :                 ConsistentGravityLinker() :
      83              :                         m_spDensity(NULL), m_spDDensity(NULL),
      84            0 :                         m_gravity(0), m_noDerivatives(false)
      85              :                 {
      86              :                         this->set_num_input(1);
      87            0 :                 }
      88              : 
      89              : 
      90            0 :                 inline void evaluate (MathVector<dim>& value,
      91              :                                       const MathVector<dim>& globIP,
      92              :                                       number time, int si) const
      93              :                 {
      94            0 :                         UG_THROW("ConsistentGravityLinker: Element required for evaluation.")
      95              :                 }
      96              : 
      97              :                 template <int refDim>
      98            0 :                 inline void evaluate(MathVector<dim> vValue[],
      99              :                                      const MathVector<dim> vGlobIP[],
     100              :                                      number time, int si,
     101              :                                      GridObject* elem,
     102              :                                      const MathVector<dim> vCornerCoords[],
     103              :                                      const MathVector<refDim> vLocalIP[],
     104              :                                      const size_t nip,
     105              :                                      LocalVector* u,
     106              :                                      const MathMatrix<refDim, dim>* vJT = NULL) const
     107              :                 {
     108            0 :                         const ReferenceObjectID roid = elem->reference_object_id();
     109              :                         const DimReferenceElement<refDim>& refElem = ReferenceElementProvider::get<refDim>(roid);
     110              :                         const size_t nco = refElem.num(ROID_VERTEX);
     111              :                                                 
     112              :                         const LocalShapeFunctionSet<refDim>& trialSpace =
     113            0 :                                 LocalFiniteElementProvider::get<refDim>(roid, LFEID(LFEID::LAGRANGE, refDim, 1));
     114              :         
     115              :                 // consistent gravity
     116              :                         StdLinConsistentGravity<refDim> ConsGravityMethod;
     117            0 :                         std::vector<MathVector<refDim> > vConsGravity(nco);
     118            0 :                         std::vector<MathVector<refDim> > vLocalGrad(nco);
     119              :                         
     120              :                 // coefficients at the integration points
     121              :                         MathVector<dim> gravity; // we assume that the gravity is constant in the elem
     122            0 :                         std::vector<number> vDensity(nco);
     123              : 
     124            0 :                         (*m_spDensity)(&(vDensity[0]), vCornerCoords, time, si,
     125              :                                                         elem, vCornerCoords, refElem.corners(), nco, u, NULL);
     126              :                         
     127              :                         try
     128              :                         {
     129              :                                 ConsGravityMethod.template prepare<dim>
     130            0 :                                         (&(vConsGravity[0]), nco, vCornerCoords, &(vDensity[0]), m_gravity);
     131              :                         }
     132            0 :                         UG_CATCH_THROW ("ConsistentDarcyVelLinker: Cannot prepare the consistent gravity.");
     133              :                         
     134              :                 // get jacobians of the transformation mapping if not passed
     135              :                         std::vector<MathMatrix<refDim, dim> > vJT_;
     136            0 :                         if(vJT == NULL)
     137              :                         {
     138              :                                 DimReferenceMapping<refDim, dim>& mapping
     139              :                                         = ReferenceMappingProvider::get<refDim, dim>(roid, vCornerCoords);
     140            0 :                                 vJT_.resize(nip);
     141            0 :                                 mapping.jacobian_transposed(&(vJT_[0]), vLocalIP, nip);
     142              :                                 vJT = &(vJT_[0]);
     143              :                         }
     144              :                         
     145            0 :                         for(size_t ip = 0; ip < nip; ++ip)
     146              :                         {
     147              :                         //      get the local gradient (assuming the Lagrange-1 basis functions)
     148            0 :                                 trialSpace.grads(&(vLocalGrad[0]), vLocalIP[ip]);
     149              :                                 
     150              :                         //      get the inverse Jacobian
     151              :                                 MathMatrix<dim,refDim> JTInv;
     152            0 :                                 RightInverse(JTInv, vJT[ip]);
     153              : 
     154              :                         //      compute [rho*g]_consistent
     155              :                                 ConsGravityMethod.template compute<dim>
     156            0 :                                         (vValue[ip], vLocalIP[ip], JTInv, &(vLocalGrad[0]), &(vConsGravity[0]));
     157              :                         }
     158            0 :                 }
     159              :                 
     160              :                 template <int refDim>
     161            0 :                 void prepare_dim_elem(GridObject* elem,
     162              :                                                         const ReferenceObjectID roid,
     163              :                                                         const MathVector<dim> vCornerCoords[])
     164              :                 {
     165              :                         const DimReferenceElement<refDim>& refElem = ReferenceElementProvider::get<refDim>(roid);
     166              :                         
     167            0 :                         m_densityCornerS = m_spDensity->template register_local_ip_series<refDim>
     168            0 :                                 (refElem.corners(), refElem.num(0), this->time_point(), false);
     169            0 :                         m_spDensity->set_global_ips(m_densityCornerS, vCornerCoords, refElem.num(0));
     170            0 :                 }
     171              : 
     172            0 :                 virtual void prepare_element(GridObject* elem, const MathVector<dim> vCornerCoords[])
     173              :                 {
     174            0 :                         const ReferenceObjectID roid = elem->reference_object_id();
     175              :                         const ReferenceElement& refElem = ReferenceElementProvider::get(roid);
     176              :                         const int ref_dim = refElem.dimension();
     177            0 :                         switch(ref_dim)
     178              :                         {
     179            0 :                                 case 1: this->template prepare_dim_elem<1> (elem, roid, vCornerCoords); break;
     180            0 :                                 case 2: this->template prepare_dim_elem<2> (elem, roid, vCornerCoords); break;
     181            0 :                                 case 3: this->template prepare_dim_elem<3> (elem, roid, vCornerCoords); break;
     182            0 :                                 default: UG_THROW("ConsistentDarcyVelLinker: Ref. dimension " << ref_dim << " not supported.");
     183              :                         }
     184            0 :                 }
     185              : 
     186              :                 template <int refDim>
     187            0 :                 void eval_and_deriv(MathVector<dim> vValue[],
     188              :                                     const MathVector<dim> vGlobIP[],
     189              :                                     number time, int si,
     190              :                                     GridObject* elem,
     191              :                                     const MathVector<dim> vCornerCoords[],
     192              :                                     const MathVector<refDim> vLocalIP[],
     193              :                                     const size_t nip,
     194              :                                     LocalVector* u,
     195              :                                     bool bDeriv,
     196              :                                     int s,
     197              :                                     std::vector<std::vector<MathVector<dim> > > vvvDeriv[],
     198              :                                     const MathMatrix<refDim, dim>* vJT = NULL) const
     199              :                 {
     200            0 :                         const ReferenceObjectID roid = elem->reference_object_id();
     201              :                         const DimReferenceElement<refDim>& refElem = ReferenceElementProvider::get<refDim>(roid);
     202              :                         const size_t nco = refElem.num(ROID_VERTEX);
     203              :                                                 
     204              :                         const LocalShapeFunctionSet<refDim>& trialSpace =
     205            0 :                                 LocalFiniteElementProvider::get<refDim>(roid, LFEID(LFEID::LAGRANGE, refDim, 1));
     206              :         
     207              :                 //      consistent gravity
     208              :                         StdLinConsistentGravity<refDim> ConsGravityMethod;
     209            0 :                         std::vector<MathVector<refDim> > vConsGravity(nco);
     210              :                         
     211              :                 //      inverse jacobians of the transformation at the integration points
     212            0 :                         std::vector<MathMatrix<dim,refDim> > vJTInv(nip);
     213              :                         
     214              :                 //      local gradients at the integration points
     215            0 :                         std::vector<MathVector<refDim> > vLocalGrad(nco);
     216              :                         
     217              :                 //      get the data of the ip series
     218            0 :                         const number* vDensity = m_spDensity->values(m_densityCornerS);
     219              : 
     220              :                 //      prepare the consistent gravity term
     221              :                         try
     222              :                         {
     223              :                                 ConsGravityMethod.template prepare<dim>
     224            0 :                                         (&(vConsGravity[0]), nco, vCornerCoords, vDensity, m_gravity);
     225              :                         }
     226            0 :                         UG_CATCH_THROW ("ConsistentGravityLinker: Cannot prepare the consistent gravity.");
     227              : 
     228              :                         // get jacobians of the transformation mapping if not passed
     229              :                         std::vector<MathMatrix<refDim, dim> > vJT_;
     230            0 :                         if(vJT == NULL)
     231              :                         {
     232              :                                 DimReferenceMapping<refDim, dim>& mapping
     233              :                                         = ReferenceMappingProvider::get<refDim, dim>(roid, vCornerCoords);
     234            0 :                                 vJT_.resize(nip);
     235            0 :                                 mapping.jacobian_transposed(&(vJT_[0]), vLocalIP, nip);
     236              :                                 vJT = &(vJT_[0]);
     237              :                         }
     238              :                         
     239            0 :                         for(size_t ip = 0; ip < nip; ++ip)
     240              :                         {
     241              :                         //      get the local gradient (assuming the Lagrange-1 basis functions)
     242            0 :                                 trialSpace.grads(&(vLocalGrad[0]), vLocalIP[ip]);
     243              :                                 
     244              :                         //      get the inverse Jacobian
     245            0 :                                 RightInverse(vJTInv[ip], vJT[ip]);
     246              : 
     247              :                         //      compute [rho*g]_consistent
     248              :                                 ConsGravityMethod.template compute<dim>
     249            0 :                                         (vValue[ip], vLocalIP[ip], vJTInv[ip], &(vLocalGrad[0]), &(vConsGravity[0]));
     250              :                         }
     251              : 
     252            0 :                         if(!bDeriv)
     253              :                                 return;
     254              :                 
     255              :         //      Compute the derivatives at all ips
     256              : 
     257            0 :                         this->set_zero(vvvDeriv, nip);
     258              :                         
     259            0 :                         if(m_noDerivatives || this->zero_derivative() || (!m_spDDensity.valid()) || m_spDDensity->zero_derivative())
     260            0 :                                 return;
     261              : 
     262              :         //  prepare derivatives of the primary function at the corners
     263            0 :             std::vector<std::vector<MathVector<refDim> > > vvDConsGravity(nco);
     264              :             try
     265              :             {
     266            0 :                 std::vector<number> DCoVal(nco);
     267            0 :                 DCoVal.assign(nco, 0);
     268            0 :                 for (size_t co = 0; co < nco; co++)
     269              :                 {
     270            0 :                     DCoVal[co] = 1;
     271            0 :                     vvDConsGravity[co].resize(nco);
     272              :                     ConsGravityMethod.template prepare<dim>
     273            0 :                         (&(vvDConsGravity[co][0]), nco, vCornerCoords, &(DCoVal[0]), m_gravity);
     274            0 :                     DCoVal[co] = 0;
     275              :                 }
     276            0 :             }
     277            0 :             UG_CATCH_THROW ("ConsistentGravityLinker: Cannot prepare Consistent Gravity for its derivatives.");
     278              :         
     279              :                 //      compute the derivatives of the density
     280            0 :                         if(m_noDerivatives || m_spDDensity->zero_derivative())
     281              :                                 return;
     282              :                         
     283            0 :                         for(size_t fct = 0; fct < m_spDDensity->num_fct(); ++fct) // fct = concentration, pressure, ...
     284              :                         {
     285              :                         //      get common fct id for this function
     286              :                                 const size_t commonFct = this->input_common_fct(_RHO_, fct);
     287            0 :                                 if(this->num_sh(commonFct) != nco)
     288            0 :                                         UG_THROW ("ConsistentGravityLinker: Number of shapes mismatch.");
     289              :                                 
     290            0 :                                 for(size_t ip = 0; ip < nip; ++ip) // we derive the cons. grav. at this ip
     291              :                                 {
     292            0 :                                         trialSpace.grads(&(vLocalGrad[0]), vLocalIP[ip]);
     293              :                                         
     294            0 :                                         for(size_t co = 0; co < nco; ++co) // w.r.t to the DoF at this corner (shape idx.)
     295              :                                         {
     296            0 :                                                 const number* vDDensity = m_spDDensity->deriv(m_densityCornerS, co, fct);
     297            0 :                                                 MathVector<dim>& deriv = vvvDeriv[ip][commonFct][co];
     298              :                                                 
     299            0 :                                                 ConsGravityMethod.template compute<dim>(deriv,
     300              :                                                         vLocalIP[ip], vJTInv[ip], &(vLocalGrad[0]), &(vvDConsGravity[co][0]));
     301            0 :                                                 VecScale(deriv, deriv, vDDensity[co]);
     302              :                                                 
     303              :                                                 /* Note that here we assume that the density has the local dependence
     304              :                                                  * on the arguments (concentration, pressure, ...): The density at
     305              :                                                  * corner co depends only on the DoFs at that corner. However, this
     306              :                                                  * excludes any differential operators, interpolations etc.
     307              :                                                  */
     308              :                                         }
     309              :                                 }
     310              :                         }
     311            0 :                 }
     312              : 
     313              :         public:
     314              :         
     315              :         ///     set density import
     316            0 :                 void set_density(SmartPtr<CplUserData<number, dim> > data)
     317              :                 {
     318            0 :                         m_spDensity = data;
     319            0 :                         m_spDDensity = data.template cast_dynamic<DependentUserData<number, dim> >();
     320            0 :                         base_type::set_input(_RHO_, data, data);
     321            0 :                 }
     322              : 
     323            0 :                 void set_density(number val)
     324              :                 {
     325            0 :                         set_density(make_sp(new ConstUserNumber<dim>(val)));
     326            0 :                 }
     327              : 
     328              :         ///     set gravity vector
     329              :                 void set_gravity(MathVector<dim> g)
     330              :                 {
     331              :                         m_gravity = g;
     332              :                 }
     333              :         
     334              :         /// set gravity from an array
     335            0 :                 void set_gravity(const std::vector<number>& vGravity)
     336              :                 {
     337            0 :                         if(vGravity.size() != dim)
     338            0 :                                 UG_THROW("ConsistentGravityLinker: Illegal dimension of the specified gravity vector.");
     339            0 :                         for(size_t i = 0; i < dim; i++) m_gravity[i] = vGravity[i];
     340            0 :                 }
     341              :         
     342              :         ///     set gravity in the z direction
     343            0 :                 void set_gravity(number g)
     344              :                 {
     345              :                         m_gravity = 0;
     346            0 :                         m_gravity[dim-1] = g;
     347            0 :                 }
     348              :         
     349              :         protected:
     350              :         ///     import density
     351              :                 static const size_t _RHO_ = 0;
     352              :                 SmartPtr<CplUserData<number, dim> > m_spDensity;
     353              :                 SmartPtr<DependentUserData<number, dim> > m_spDDensity;
     354              :                 size_t m_densityCornerS;
     355              : 
     356              :         ///     constant gravity
     357              :                 MathVector<dim> m_gravity;
     358              : 
     359              : 
     360              :         public:
     361            0 :                 void set_no_derivatives(bool v) { m_noDerivatives = v; }
     362              : 
     363              :         protected:
     364              :                 // disable the derivatives
     365              :                 bool m_noDerivatives;
     366              : };
     367              : 
     368              : } // end namespace ug
     369              : 
     370              : #endif /* __H__UG__LIB_DISC__SPATIAL_DISC__CONSISTENT_GRAVITY_LINKER__ */
        

Generated by: LCOV version 2.0-1