LCOV - code coverage report
Current view: top level - ugbase/lib_disc/spatial_disc/disc_util - hfv1_geom.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 246 0
Test Date: 2025-09-21 23:31:46 Functions: 0.0 % 1194 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__DISC_HELPER__HANGING_FINITE_VOLUME_GEOMETRY__
      34              : #define __H__UG__LIB_DISC__SPATIAL_DISC__DISC_HELPER__HANGING_FINITE_VOLUME_GEOMETRY__
      35              : 
      36              : // extern libraries
      37              : #include <cmath>
      38              : #include <vector>
      39              : 
      40              : // other ug4 modules
      41              : #include "common/common.h"
      42              : 
      43              : // library intern includes
      44              : #include "lib_disc/reference_element/reference_element.h"
      45              : #include "lib_disc/local_finite_element/local_finite_element_provider.h"
      46              : #include "fv_util.h"
      47              : #include "fv1_geom.h"
      48              : 
      49              : namespace ug{
      50              : 
      51              : ////////////////////////////////////////////////////////////////////////////////
      52              : // Hanging node FV1 Geometry for Reference Element Type
      53              : ////////////////////////////////////////////////////////////////////////////////
      54              : 
      55              : /// Geometry and shape functions for 1st order Vertex-Centered Finite Volume with the hanging nodes
      56              : /**
      57              :  * \tparam      TElem           Element type
      58              :  * \tparam      TWorldDim       (physical) world dimension
      59              :  */
      60              : template <   typename TElem, int TWorldDim>
      61              : class HFV1Geometry : public FVGeometryBase{
      62              :         private:
      63              :         /// type of reference element
      64              :                 typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type;
      65              : 
      66              :         /// number of SubControlVolumes
      67              :                 static const size_t m_numNaturalSCV = ref_elem_type::numCorners;
      68              : 
      69              :         /// number of SubControlVolumeFaces
      70              :                 static const size_t m_numNaturalSCVF = ref_elem_type::numEdges;
      71              : 
      72              :         public:
      73              :         /// dimension of reference element
      74              :                 static const int dim = ref_elem_type::dim;
      75              : 
      76              :         /// dimension of world
      77              :                 static const int worldDim = TWorldDim;
      78              : 
      79              :         /// Hanging node flag: this Geometry does support hanging nodes
      80              :                 static const bool usesHangingNodes = true;
      81              : 
      82              :         /// flag indicating if local data may change
      83              :                 static const bool staticLocalData = true;
      84              : 
      85              :         protected:
      86              :                 struct MidID
      87              :                 {
      88            0 :                                 MidID() : dim(0), id(0) {};
      89            0 :                                 MidID(size_t dim_, size_t id_) : dim(dim_), id(id_) {};
      90              :                                 size_t dim;
      91              :                                 size_t id;
      92              :                 };
      93              : 
      94              :         public:
      95              :                 class SCVF
      96              :                 {
      97              :                         public:
      98              :                         /// dimension of reference element
      99              :                                 static const int dim = ref_elem_type::dim;
     100              : 
     101              :                         /// dimension of world
     102              :                                 static const int worldDim = TWorldDim;
     103              : 
     104              :                         private:
     105              :                         /// let outer class access private members
     106              :                                 friend class HFV1Geometry<TElem, TWorldDim>;
     107              : 
     108              :                         /// number of integration points
     109              :                                 static const size_t m_numIP = 1;
     110              : 
     111              :                         /// Number of corners of scvf
     112              :                                 static const size_t m_numCorners = hfv1_traits<ref_elem_type, TWorldDim>::NumCornersOfSCVF;
     113              : 
     114              :                         public:
     115            0 :                                 SCVF() {};
     116              : 
     117              :                         /// index of SubControlVolume on one side of the scvf
     118              :                         /// NO! return value is the associated NODE_ID; this is not the same!
     119            0 :                                 inline size_t from() const {return m_from;}
     120              : 
     121              :                         /// index of SubControlVolume on one side of the scvf
     122              :                         /// NO! return value is the associated NODE_ID; this is not the same!
     123            0 :                                 inline size_t to() const {return m_to;}
     124              : 
     125              :                         /// number of integration points on scvf
     126            0 :                                 inline size_t num_ip() const {return m_numIP;}
     127              : 
     128              :                         /// local integration point of scvf
     129            0 :                                 inline const MathVector<dim>& local_ip() const {return localIP;}
     130              : 
     131              :                         /// global integration point of scvf
     132            0 :                                 inline const MathVector<worldDim>& global_ip() const {return globalIP;}
     133              : 
     134              :                         /// normal on scvf (points direction "from"->"to"). Norm is equal to area
     135            0 :                                 inline const MathVector<worldDim>& normal() const {return Normal;} // includes area
     136              : 
     137              :                         /// Transposed Inverse of Jacobian in integration point
     138            0 :                                 inline const MathMatrix<worldDim,dim>& JTInv() const {return JtInv;}
     139              : 
     140              :                         /// Determinante of Jacobian in integration point
     141            0 :                                 inline number detJ() const {return detj;}
     142              : 
     143              :                         /// number of shape functions
     144            0 :                                 inline size_t num_sh() const {return vShape.size();}
     145              : 
     146              :                         /// value of shape function i in integration point
     147            0 :                                 inline number shape(size_t sh) const
     148            0 :                                         {UG_ASSERT(sh < num_sh(), "Invalid ip index"); return vShape[sh];}
     149              : 
     150              :                         /// value of local gradient of shape function i in integration point
     151            0 :                                 inline const MathVector<dim>& local_grad(size_t sh) const
     152            0 :                                         {UG_ASSERT(sh < num_sh(), "Invalid ip index"); return localGrad[sh];}
     153              : 
     154              :                         /// vector of local gradients in ip point
     155            0 :                                 inline const MathVector<dim>* local_grad_vector() const {return &localGrad[0];}
     156              : 
     157              :                         /// value of global gradient of shape function i in integration point
     158            0 :                                 inline const MathVector<worldDim>& global_grad(size_t sh) const
     159            0 :                                         {UG_ASSERT(sh < num_sh(), "Invalid ip index"); return globalGrad[sh];}
     160              : 
     161              :                         /// vector of global gradients in ip point
     162            0 :                                 inline const MathVector<worldDim>* global_grad_vector() const {return &globalGrad[0];}
     163              : 
     164              :                         /// number of corners, that bound the scvf
     165            0 :                                 inline size_t num_corners() const {return m_numCorners;}
     166              : 
     167              :                         /// return local corner number i
     168            0 :                                 inline const MathVector<dim>& local_corner(size_t co) const
     169            0 :                                         {UG_ASSERT(co < num_corners(), "Invalid corner index."); return m_vLocPos[co];}
     170              : 
     171              :                         /// return glbal corner number i
     172            0 :                                 inline const MathVector<worldDim>& global_corner(size_t co) const
     173            0 :                                         {UG_ASSERT(co < num_corners(), "Invalid corner index."); return m_vGloPos[co];}
     174              : 
     175              :                         private:
     176              :                                 // This scvf separates the scv with the ids given in "from" and "to"
     177              :                                 // The computed normal points in direction from->to
     178              :                                 size_t m_from, m_to;
     179              : 
     180              :                                 // ordering is:
     181              :                                 // 2D: edgeMidPoint, CenterOfElement
     182              :                                 // 3D: edgeMidPoint, Side one, CenterOfElement, Side two
     183              :                                 MathVector<dim> m_vLocPos[m_numCorners]; // local corners of scvf
     184              :                                 MathVector<worldDim> m_vGloPos[m_numCorners]; // global corners of scvf
     185              :                                 MidID m_midId[m_numCorners]; // dimension and id of object, that's midpoint bounds the scvf
     186              : 
     187              :                                 // scvf part
     188              :                                 MathVector<dim> localIP; // local integration point
     189              :                                 MathVector<worldDim> globalIP; // global intergration point
     190              :                                 MathVector<worldDim> Normal; // normal (incl. area)
     191              : 
     192              :                                 // shapes and derivatives
     193              :                                 std::vector<number> vShape; // shapes at ip
     194              :                                 std::vector<MathVector<dim> > localGrad; // local grad at ip
     195              :                                 std::vector<MathVector<worldDim> > globalGrad; // global grad at ip
     196              :                                 MathMatrix<worldDim,dim> JtInv; // Jacobian transposed at ip
     197              :                                 number detj; // Jacobian det at ip
     198              :                 };
     199              : 
     200              :                 class SCV
     201              :                 {
     202              :                         private:
     203              :                         //  let outer class access private members
     204              :                                 friend class HFV1Geometry<TElem, TWorldDim>;
     205              : 
     206              :                         /// number of integration points
     207              :                                 static const size_t m_numIP = 1;
     208              : 
     209              :                         /// Number of corners of scvf
     210              :                                 static const size_t m_maxNumCorners = hfv1_traits<ref_elem_type, TWorldDim>::MaxNumCornersOfSCV;
     211              : 
     212              :                         /// type of element the subcontrol volume represents
     213              :                                 typedef typename hfv1_traits<ref_elem_type, TWorldDim>::scv_type scv_type;
     214              : 
     215              :                         public:
     216            0 :                                 SCV() : m_numCorners(m_maxNumCorners) {};
     217              : 
     218              :                         /// node id that this scv is associated to
     219            0 :                                 inline size_t node_id() const {return nodeId;}
     220              : 
     221              :                         /// number of integration points
     222            0 :                                 inline size_t num_ip() const {return m_numIP;}
     223              : 
     224              :                         /// local integration point of scv
     225            0 :                                 inline const MathVector<dim>& local_ip() const {return m_vLocPos[0];}
     226              : 
     227              :                         /// global integration point
     228            0 :                                 inline const MathVector<worldDim>& global_ip() const {return m_vGloPos[0];}
     229              : 
     230              :                         /// volume of scv
     231            0 :                                 inline number volume() const {return vol;}
     232              : 
     233              :                         /// number of corners, that bound the scvf
     234            0 :                                 inline size_t num_corners() const {return m_numCorners;}
     235              : 
     236              :                         /// return local corner number i
     237            0 :                                 inline const MathVector<dim>& local_corner(size_t co) const
     238            0 :                                         {UG_ASSERT(co < num_corners(), "Invalid corner index."); return m_vLocPos[co];}
     239              : 
     240              :                         /// return global corner number i
     241            0 :                                 inline const MathVector<worldDim>& global_corner(size_t co) const
     242            0 :                                         {UG_ASSERT(co < num_corners(), "Invalid corner index."); return m_vGloPos[co];}
     243              : 
     244              :                         private:
     245              :                                 size_t nodeId; // node id of associated node
     246              :                                 size_t m_numCorners;
     247              : 
     248              :                                 // The ordering is: Corner, ...
     249              :                                 MathVector<dim> m_vLocPos[m_maxNumCorners]; // local position of node
     250              :                                 MathVector<worldDim> m_vGloPos[m_maxNumCorners]; // global position of node
     251              :                                 MidID m_midId[m_maxNumCorners]; // dimension and id of object, that's midpoint bounds the scv
     252              :                                 number vol;
     253              :                 };
     254              : 
     255              : 
     256              :         public:
     257              :         ///     constructor
     258              :                 HFV1Geometry();
     259              : 
     260              :         ///     update values for an element
     261              :                 void update(GridObject* pElem, const MathVector<worldDim>* vCornerCoords,
     262              :                                                  const ISubsetHandler* ish = NULL);
     263              : 
     264              :         //      debug output
     265              :                 void print();
     266              : 
     267              :         ///     get the element
     268            0 :                 GridObject* elem() const {return m_pElem;}
     269              : 
     270              :         public:
     271              :         /// number of SubControlVolumeFaces
     272            0 :                 inline size_t num_scvf() const {return m_vSCVF.size();}
     273              : 
     274              :         /// const access to SubControlVolumeFace number i
     275            0 :                 inline const SCVF& scvf(size_t i) const
     276            0 :                         {UG_ASSERT(i < num_scvf(), "Invalid Index."); return m_vSCVF[i];}
     277              : 
     278              :         /// number of SubControlVolumes
     279            0 :                 size_t num_scv() const {return m_vSCV.size();}
     280              : 
     281              :         /// const access to SubControlVolume number i
     282            0 :                 inline const SCV& scv(size_t i) const
     283            0 :                         {UG_ASSERT(i < num_scv(), "Invalid Index."); return m_vSCV[i];}
     284              : 
     285              :         /// number of shape functions
     286            0 :                 inline size_t num_sh() const
     287              :                 {
     288            0 :                         return m_numSh;
     289              :                 };
     290              : 
     291              :         public:
     292              :         /// returns number of all scv ips
     293            0 :                 size_t num_scvf_ips() const {return m_vGlobSCVFIP.size();}
     294              : 
     295              :         /// returns all ips of scv as they appear in scv loop
     296            0 :                 const MathVector<worldDim>* scvf_global_ips() const {return &m_vGlobSCVFIP[0];}
     297              : 
     298              :         /// returns all ips of scv as they appear in scv loop
     299            0 :                 const MathVector<dim>* scvf_local_ips() const {return &m_vLocSCVFIP[0];}
     300              : 
     301              :         /// returns number of all scv ips
     302            0 :                 size_t num_scv_ips() const {return m_vGlobSCVIP.size();}
     303              : 
     304              :         /// returns all ips of scv as they appear in scv loop
     305            0 :                 const MathVector<worldDim>* scv_global_ips() const {return &m_vGlobSCVIP[0];}
     306              : 
     307              :         /// returns all ips of scv as they appear in scv loop
     308            0 :                 const MathVector<dim>* scv_local_ips() const {return &m_vLocSCVIP[0];}
     309              : 
     310              :         /// return local coords for node ID
     311            0 :                 const MathVector<dim>& local_node_position(size_t nodeID) const
     312              :                 {
     313              :                         UG_ASSERT(nodeID < m_locMid[0].size(), "Invalid node id.");
     314            0 :                         return m_locMid[0][nodeID];
     315              :                 }
     316              : 
     317              :         /// return global coords for node ID
     318            0 :                 const MathVector<worldDim>& global_node_position(size_t nodeID) const
     319              :                 {
     320              :                         UG_ASSERT(nodeID < m_gloMid[0].size(), "Invalid node id.");
     321            0 :                         return m_gloMid[0][nodeID];
     322              :                 }
     323              : 
     324              :         protected:
     325              :                 std::vector<MathVector<worldDim> > m_vGlobSCVFIP;
     326              :                 std::vector<MathVector<dim> > m_vLocSCVFIP;
     327              :                 std::vector<MathVector<worldDim> > m_vGlobSCVIP;
     328              :                 std::vector<MathVector<dim> > m_vLocSCVIP;
     329              : 
     330              :         protected:
     331            0 :                 void copy_local_corners(SCVF& scvf)
     332              :                 {
     333            0 :                         for(size_t i = 0; i < scvf.num_corners(); ++i)
     334              :                         {
     335            0 :                                 const size_t dim = scvf.m_midId[i].dim;
     336            0 :                                 const size_t id = scvf.m_midId[i].id;
     337              :                                 scvf.m_vLocPos[i] = m_locMid[dim][id];
     338              :                         }
     339            0 :                 }
     340              : 
     341            0 :                 void copy_global_corners(SCVF& scvf)
     342              :                 {
     343            0 :                         for(size_t i = 0; i < scvf.num_corners(); ++i)
     344              :                         {
     345            0 :                                 const size_t dim = scvf.m_midId[i].dim;
     346            0 :                                 const size_t id = scvf.m_midId[i].id;
     347              :                                 scvf.m_vGloPos[i] = m_gloMid[dim][id];
     348              :                         }
     349            0 :                 }
     350              : 
     351            0 :                 void copy_local_corners(SCV& scv)
     352              :                 {
     353            0 :                         for(size_t i = 0; i < scv.num_corners(); ++i)
     354              :                         {
     355            0 :                                 const size_t dim_ = scv.m_midId[i].dim;
     356            0 :                                 const size_t id = scv.m_midId[i].id;
     357              :                                 UG_ASSERT(dim_ <= (size_t)dim, "Dimension wrong");
     358              :                                 UG_ASSERT(id < m_locMid[dim_].size(), "id " << id << " in dim="
     359              :                                           <<dim_<<" wrong. (size is "<< m_locMid[dim_].size()<<")\n");
     360              :                                 scv.m_vLocPos[i] = m_locMid[dim_][id];
     361              :                         }
     362            0 :                 }
     363              : 
     364            0 :                 void copy_global_corners(SCV& scv)
     365              :                 {
     366            0 :                         for(size_t i = 0; i < scv.num_corners(); ++i)
     367              :                         {
     368            0 :                                 const size_t dim_ = scv.m_midId[i].dim;
     369            0 :                                 const size_t id = scv.m_midId[i].id;
     370              :                                 UG_ASSERT(dim_ <= (size_t)dim, "Dimension wrong");
     371              :                                 UG_ASSERT(id < m_gloMid[dim_].size(), "id " << id << " in dim="
     372              :                                           <<dim_<<" wrong. (size is "<< m_gloMid[dim_].size()<<")\n");
     373              :                                 scv.m_vGloPos[i] = m_gloMid[dim_][id];
     374              :                         }
     375            0 :                 }
     376              : 
     377              :                 // i = number of side
     378            0 :                 void compute_side_midpoints(size_t i,
     379              :                                             MathVector<dim>& locSideMid,
     380              :                                             MathVector<worldDim>& gloSideMid)
     381              :                 {
     382              :                         if(dim>1)
     383              :                         {
     384            0 :                                 const size_t coID0 = m_rRefElem.id(2, i, 0, 0);
     385              :                                 locSideMid = m_locMid[0][coID0];
     386              :                                 gloSideMid = m_gloMid[0][coID0];
     387              : 
     388              :                                 // add corner coordinates of the corners of the geometric object
     389            0 :                                 for(size_t j = 1; j < m_rRefElem.num(2, i, 0); ++j)
     390              :                                 {
     391            0 :                                         const size_t coID = m_rRefElem.id(2, i, 0, j);
     392              :                                         locSideMid += m_locMid[0][coID];
     393              :                                         gloSideMid += m_gloMid[0][coID];
     394              :                                 }
     395              : 
     396              :                                 // scale for correct averaging
     397            0 :                                 locSideMid *= 1./(m_rRefElem.num(2, i, 0));
     398              :                                 gloSideMid *= 1./(m_rRefElem.num(2, i, 0));
     399              :                         }
     400            0 :                 }
     401              : 
     402              :                 // i, j, k, l = number nodes
     403            0 :                 void compute_side_midpoints(size_t i, size_t j, size_t k, size_t l,
     404              :                                                                         MathVector<dim>& locSideMid,
     405              :                                                                         MathVector<worldDim>& gloSideMid)
     406              :                 {
     407              :                         VecAdd(locSideMid, m_locMid[0][i], m_locMid[0][j], m_locMid[0][k], m_locMid[0][l]);
     408              :                         VecAdd(gloSideMid, m_gloMid[0][i], m_gloMid[0][j], m_gloMid[0][k], m_gloMid[0][l]);
     409              : 
     410              :                         // scale for correct averaging
     411              :                         locSideMid *= 0.25;
     412              :                         gloSideMid *= 0.25;
     413            0 :                 }
     414              : 
     415              :                 // i, j, k = number nodes
     416            0 :                 void compute_side_midpoints(size_t i, size_t j, size_t k,
     417              :                                                                         MathVector<dim>& locSideMid, MathVector<worldDim>& gloSideMid)
     418              :                 {
     419              :                         VecAdd(locSideMid, m_locMid[0][i], m_locMid[0][j], m_locMid[0][k]);
     420              :                         VecAdd(gloSideMid, m_gloMid[0][i], m_gloMid[0][j], m_gloMid[0][k]);
     421              : 
     422              :                         // scale for correct averaging
     423              :                         locSideMid *= 1./3.;
     424              :                         gloSideMid *= 1./3.;
     425            0 :                 }
     426              : 
     427              :                 // returns edgeID of child edge, that has corner co. i is the natural edge index
     428            0 :                 size_t get_child_edge_of_corner(size_t i, size_t co)
     429              :         {
     430            0 :                 for(size_t e = 0; e < m_vNatEdgeInfo[i].num_child_edges(); ++e)
     431              :                 {
     432              :                         const size_t childId = m_vNatEdgeInfo[i].child_edge(e);
     433            0 :                         if(m_vNewEdgeInfo[childId].from() == co)
     434            0 :                                 return childId;
     435            0 :                         if(m_vNewEdgeInfo[childId].to() == co)
     436            0 :                                 return childId;
     437              :                 }
     438              :                 return -1;
     439              :         }
     440              : 
     441              :         private:
     442              :                 struct NewEdgeInfo
     443              :                 {
     444              :                         friend class HFV1Geometry<TElem, TWorldDim>;
     445              :                 public:
     446            0 :                         NewEdgeInfo() : m_from(-1), m_to(-1){}
     447            0 :             size_t from() const {return m_from;}
     448            0 :             size_t to() const {return m_to;}
     449              :                 private:
     450              :                         size_t m_from;
     451              :                         size_t m_to;
     452              :                 };
     453              : 
     454              :         struct NatEdgeInfo
     455              :         {
     456              :                 friend class HFV1Geometry<TElem, TWorldDim>;
     457              :             public:
     458            0 :                 NatEdgeInfo() : nodeId(-1), numChildEdges(0) {for(size_t i=0; i<2; ++i) childEdge[i] = -1;}
     459            0 :                 bool is_hanging() const {return numChildEdges == 2;}
     460            0 :                 size_t node_id() const {UG_ASSERT(is_hanging(), "Should only be called, if edge is hanging."); return nodeId;}
     461            0 :                 size_t num_child_edges() const {return numChildEdges;}
     462            0 :                 size_t child_edge(size_t i) const {UG_ASSERT(i < num_child_edges(), "Wrong id."); return childEdge[i];}
     463              : 
     464              :             private:
     465              :                 size_t nodeId;
     466              :                 size_t numChildEdges;
     467              :                 size_t childEdge[2];
     468              :         };
     469              : 
     470              :     //  help array: maps NaturalEdge -> NodeOnEdge (-1 if no node on edge)
     471              :         std::vector<NatEdgeInfo> m_vNatEdgeInfo;
     472              :         std::vector<NewEdgeInfo> m_vNewEdgeInfo;
     473              : 
     474              :         private:
     475              :         //      pointer to current element
     476              :                 GridObject* m_pElem;
     477              : 
     478              :                 std::vector<MathVector<dim> > m_locMid[dim+1];
     479              :                 std::vector<MathVector<worldDim> > m_gloMid[dim+1];
     480              : 
     481              :         //      SubControlVolumeFaces
     482              :                 std::vector<SCVF> m_vSCVF;
     483              : 
     484              :         //      SubControlVolumes
     485              :                 std::vector<SCV> m_vSCV;
     486              : 
     487              :         //      number of shape functions
     488              :                 size_t m_numSh;
     489              : 
     490              :         //      Reference Mapping
     491              :                 ReferenceMapping<ref_elem_type, worldDim> m_rMapping;
     492              : 
     493              :         //      Reference Element
     494              :                 const ref_elem_type& m_rRefElem;
     495              : };
     496              : 
     497              : template <   int TDim, int TWorldDim = TDim>
     498              : class DimHFV1Geometry : public FVGeometryBase{
     499              :         private:
     500              :         /// number of SubControlVolumes
     501              :                 size_t m_numNaturalSCV;
     502              : 
     503              :         /// number of SubControlVolumeFaces
     504              :                 size_t m_numNaturalSCVF;
     505              :                 
     506              :         /// max number of shapes
     507              :                 static const size_t m_maxNSH = fv1_dim_traits<TDim, TWorldDim>::maxNSH;
     508              : 
     509              :         public:
     510              :         /// dimension of reference element
     511              :                 static const int dim = TDim;
     512              : 
     513              :         /// dimension of world
     514              :                 static const int worldDim = TWorldDim;
     515              : 
     516              :         /// Hanging node flag: this Geometry does support hanging nodes
     517              :                 static const bool usesHangingNodes = true;
     518              : 
     519              :         /// flag indicating if local data may change
     520              :                 static const bool staticLocalData = true;
     521              :                 
     522              :         /// traits      
     523              :                 typedef hdimfv1_traits<TDim> traits;
     524              :                 
     525              :         /// element type names
     526              :                 typedef typename traits::elem_type_0 elem_type_0;
     527              :                 typedef typename traits::elem_type_1 elem_type_1;
     528              :                 typedef typename traits::elem_type_2 elem_type_2;
     529              :                 typedef typename traits::elem_type_3 elem_type_3;
     530              :                 typedef typename traits::elem_type_4 elem_type_4;
     531              : 
     532              :         protected:
     533              :                 struct MidID
     534              :                 {
     535            0 :                                 MidID() : dim(0), id(0) {};
     536            0 :                                 MidID(size_t dim_, size_t id_) : dim(dim_), id(id_) {};
     537              :                                 size_t dim;
     538              :                                 size_t id;
     539              :                 };
     540              : 
     541              :         public:
     542              :                 class SCVF
     543              :                 {
     544              :                         public:
     545              :                         /// dimension of reference element
     546              :                                 static const int dim = TDim;
     547              : 
     548              :                         /// dimension of world
     549              :                                 static const int worldDim = TWorldDim;
     550              : 
     551              :                         private:
     552              :                         /// let outer class access private members
     553              :                                 friend class DimHFV1Geometry<TDim, TWorldDim>;
     554              : 
     555              :                         /// number of integration points
     556              :                                 static const size_t m_numIP = 1;
     557              : 
     558              :                         /// Number of corners of scvf
     559              :                                 static const size_t m_numCorners = traits::NumCornersOfSCVF;
     560              : 
     561              :                         public:
     562            0 :                                 SCVF() {};
     563              : 
     564              :                         /// index of SubControlVolume on one side of the scvf
     565            0 :                                 inline size_t from() const {return m_from;}
     566              : 
     567              :                         /// index of SubControlVolume on one side of the scvf
     568            0 :                                 inline size_t to() const {return m_to;}
     569              : 
     570              :                         /// number of integration points on scvf
     571            0 :                                 inline size_t num_ip() const {return m_numIP;}
     572              : 
     573              :                         /// local integration point of scvf
     574            0 :                                 inline const MathVector<dim>& local_ip() const {return localIP;}
     575              : 
     576              :                         /// global integration point of scvf
     577            0 :                                 inline const MathVector<worldDim>& global_ip() const {return globalIP;}
     578              : 
     579              :                         /// normal on scvf (points direction "from"->"to"). Norm is equal to area
     580            0 :                                 inline const MathVector<worldDim>& normal() const {return Normal;} // includes area
     581              : 
     582              :                         /// Transposed Inverse of Jacobian in integration point
     583            0 :                                 inline const MathMatrix<worldDim,dim>& JTInv() const {return JtInv;}
     584              : 
     585              :                         /// Determinante of Jacobian in integration point
     586            0 :                                 inline number detJ() const {return detj;}
     587              : 
     588              :                         /// number of shape functions
     589            0 :                                 inline size_t num_sh() const {return vShape.size();}
     590              : 
     591              :                         /// value of shape function i in integration point
     592            0 :                                 inline number shape(size_t sh) const
     593            0 :                                         {UG_ASSERT(sh < num_sh(), "Invalid ip index"); return vShape[sh];}
     594              : 
     595              :                         /// value of local gradient of shape function i in integration point
     596            0 :                                 inline const MathVector<dim>& local_grad(size_t sh) const
     597            0 :                                         {UG_ASSERT(sh < num_sh(), "Invalid ip index"); return localGrad[sh];}
     598              : 
     599              :                         /// vector of local gradients in ip point
     600            0 :                                 inline const MathVector<dim>* local_grad_vector() const {return &localGrad[0];}
     601              : 
     602              :                         /// value of global gradient of shape function i in integration point
     603            0 :                                 inline const MathVector<worldDim>& global_grad(size_t sh) const
     604            0 :                                         {UG_ASSERT(sh < num_sh(), "Invalid ip index"); return globalGrad[sh];}
     605              : 
     606              :                         /// vector of global gradients in ip point
     607            0 :                                 inline const MathVector<worldDim>* global_grad_vector() const {return &globalGrad[0];}
     608              : 
     609              :                         /// number of corners, that bound the scvf
     610            0 :                                 inline size_t num_corners() const {return m_numCorners;}
     611              : 
     612              :                         /// return local corner number i
     613            0 :                                 inline const MathVector<dim>& local_corner(size_t co) const
     614            0 :                                         {UG_ASSERT(co < num_corners(), "Invalid corner index."); return m_vLocPos[co];}
     615              : 
     616              :                         /// return glbal corner number i
     617            0 :                                 inline const MathVector<worldDim>& global_corner(size_t co) const
     618            0 :                                         {UG_ASSERT(co < num_corners(), "Invalid corner index."); return m_vGloPos[co];}
     619              : 
     620              :                         private:
     621              :                                 // This scvf separates the scv with the ids given in "from" and "to"
     622              :                                 // The computed normal points in direction from->to
     623              :                                 size_t m_from, m_to;
     624              : 
     625              :                                 // ordering is:
     626              :                                 // 2D: edgeMidPoint, CenterOfElement
     627              :                                 // 3D: edgeMidPoint, Side one, CenterOfElement, Side two
     628              :                                 MathVector<dim> m_vLocPos[m_numCorners]; // local corners of scvf
     629              :                                 MathVector<worldDim> m_vGloPos[m_numCorners]; // global corners of scvf
     630              :                                 MidID m_midId[m_numCorners]; // dimension and id of object, that's midpoint bounds the scvf
     631              : 
     632              :                                 // scvf part
     633              :                                 MathVector<dim> localIP; // local integration point
     634              :                                 MathVector<worldDim> globalIP; // global intergration point
     635              :                                 MathVector<worldDim> Normal; // normal (incl. area)
     636              : 
     637              :                                 // shapes and derivatives
     638              :                                 std::vector<number> vShape; // shapes at ip
     639              :                                 std::vector<MathVector<dim> > localGrad; // local grad at ip
     640              :                                 std::vector<MathVector<worldDim> > globalGrad; // global grad at ip
     641              :                                 MathMatrix<worldDim,dim> JtInv; // Jacobian transposed at ip
     642              :                                 number detj; // Jacobian det at ip
     643              :                 };
     644              : 
     645              :                 class SCV
     646              :                 {
     647              :                         private:
     648              :                         //  let outer class access private members
     649              :                                 friend class DimHFV1Geometry<TDim, TWorldDim>;
     650              : 
     651              :                         /// number of integration points
     652              :                                 static const size_t m_numIP = 1;
     653              : 
     654              :                         /// Number of corners of scvf
     655              :                                 static const size_t m_maxNumCorners = traits::MaxNumCornersOfSCV;
     656              : 
     657              :                         /// type of element the subcontrol volume represents
     658              :                                 typedef typename traits::scv_type scv_type;
     659              : 
     660              :                         public:
     661            0 :                                 SCV() : m_numCorners(m_maxNumCorners) {};
     662              : 
     663              :                         /// node id that this scv is associated to
     664            0 :                                 inline size_t node_id() const {return nodeId;}
     665              : 
     666              :                         /// number of integration points
     667            0 :                                 inline size_t num_ip() const {return m_numIP;}
     668              : 
     669              :                         /// local integration point of scv
     670            0 :                                 inline const MathVector<dim>& local_ip() const {return m_vLocPos[0];}
     671              : 
     672              :                         /// global integration point
     673            0 :                                 inline const MathVector<worldDim>& global_ip() const {return m_vGloPos[0];}
     674              : 
     675              :                         /// volume of scv
     676            0 :                                 inline number volume() const {return vol;}
     677              : 
     678              :                         /// number of corners, that bound the scvf
     679            0 :                                 inline size_t num_corners() const {return m_numCorners;}
     680              : 
     681              :                         /// return local corner number i
     682            0 :                                 inline const MathVector<dim>& local_corner(size_t co) const
     683            0 :                                         {UG_ASSERT(co < num_corners(), "Invalid corner index."); return m_vLocPos[co];}
     684              : 
     685              :                         /// return global corner number i
     686            0 :                                 inline const MathVector<worldDim>& global_corner(size_t co) const
     687            0 :                                         {UG_ASSERT(co < num_corners(), "Invalid corner index."); return m_vGloPos[co];}
     688              :                                         
     689              :                         /// number of shape functions
     690            0 :                                 inline size_t num_sh() const {return numSH;}
     691              : 
     692              :                         /// value of shape function i in integration point
     693            0 :                                 inline number shape(size_t sh) const {return vShape[sh];}
     694              : 
     695              :                         /// vector of shape functions in ip point
     696            0 :                                 inline const number* shape_vector() const {return vShape;}
     697              : 
     698              :                         /// value of local gradient of shape function i in integration point
     699            0 :                                 inline const MathVector<dim>& local_grad(size_t sh) const
     700            0 :                                         {UG_ASSERT(sh < num_sh(), "Invalid index"); return localGrad[sh];}
     701              : 
     702              :                         /// vector of local gradients in ip point
     703            0 :                                 inline const MathVector<dim>* local_grad_vector() const {return localGrad;}
     704              : 
     705              :                         /// value of global gradient of shape function i in integration point
     706            0 :                                 inline const MathVector<worldDim>& global_grad(size_t sh) const
     707            0 :                                         {UG_ASSERT(sh < num_sh(), "Invalid index"); return globalGrad[sh];}
     708              : 
     709              :                         /// vector of global gradients in ip point
     710            0 :                                 inline const MathVector<worldDim>* global_grad_vector() const {return globalGrad;}
     711              :                                 
     712              :                         /// Transposed Inverse of Jacobian in integration point
     713            0 :                                 inline const MathMatrix<worldDim,dim>& JTInv() const {return JtInv;}
     714              : 
     715              :                         /// Determinant of Jacobian in integration point
     716            0 :                                 inline number detJ() const {return detj;}
     717              : 
     718              :                         private:
     719              :                                 size_t nodeId; // node id of associated node
     720              :                                 size_t m_numCorners;
     721              : 
     722              :                         // The ordering is: Corner, ...
     723              :                                 MathVector<dim> m_vLocPos[m_maxNumCorners]; // local position of node
     724              :                                 MathVector<worldDim> m_vGloPos[m_maxNumCorners]; // global position of node
     725              :                                 MidID m_midId[m_maxNumCorners]; // dimension and id of object, that's midpoint bounds the scv
     726              :                                 number vol;
     727              :                                 
     728              :                         // shapes and derivatives
     729              :                                 size_t numSH;
     730              :                                 number vShape[m_maxNSH]; // shapes at ip
     731              :                                 MathVector<dim> localGrad[m_maxNSH]; // local grad at ip
     732              :                                 MathVector<worldDim> globalGrad[m_maxNSH]; // global grad at ip
     733              :                                 MathMatrix<worldDim,dim> JtInv; // Jacobian transposed at ip
     734              :                                 number detj; // Jacobian det at ip
     735              :                 };
     736              : 
     737              : 
     738              :         public:
     739              :         ///     constructor
     740            0 :                 DimHFV1Geometry() : m_pElem(NULL), m_roid(ROID_UNKNOWN) {};
     741              :                 
     742              :         /// update local data for an element
     743              :                 void update_local_data();
     744              : 
     745              :         ///     update values for an element
     746              :                 void update(GridObject* pElem, const MathVector<worldDim>* vCornerCoords,
     747              :                                                  const ISubsetHandler* ish = NULL);
     748              : 
     749              :         //      debug output
     750              :         //      void print();
     751              : 
     752              :         public:
     753              :         /// number of SubControlVolumeFaces
     754            0 :                 inline size_t num_scvf() const {return m_vSCVF.size();}
     755              : 
     756              :         /// const access to SubControlVolumeFace number i
     757            0 :                 inline const SCVF& scvf(size_t i) const
     758            0 :                         {UG_ASSERT(i < num_scvf(), "Invalid Index."); return m_vSCVF[i];}
     759              : 
     760              :         /// number of SubControlVolumes
     761            0 :                 size_t num_scv() const {return m_vSCV.size();}
     762              : 
     763              :         /// const access to SubControlVolume number i
     764            0 :                 inline const SCV& scv(size_t i) const
     765            0 :                         {UG_ASSERT(i < num_scv(), "Invalid Index."); return m_vSCV[i];}
     766              : 
     767              :         /// number of shape functions
     768            0 :                 inline size_t num_sh() const
     769              :                 {
     770            0 :                         return m_numSh;
     771              :                 };
     772              : 
     773              :         public:
     774              :         /// returns number of all scv ips
     775            0 :                 size_t num_scvf_ips() const {return m_vGlobSCVFIP.size();}
     776              : 
     777              :         /// returns all ips of scv as they appear in scv loop
     778            0 :                 const MathVector<worldDim>* scvf_global_ips() const {return &m_vGlobSCVFIP[0];}
     779              : 
     780              :         /// returns all ips of scv as they appear in scv loop
     781            0 :                 const MathVector<dim>* scvf_local_ips() const {return &m_vLocSCVFIP[0];}
     782              : 
     783              :         /// returns number of all scv ips
     784            0 :                 size_t num_scv_ips() const {return m_vGlobSCVIP.size();}
     785              : 
     786              :         /// returns all ips of scv as they appear in scv loop
     787            0 :                 const MathVector<worldDim>* scv_global_ips() const {return &m_vGlobSCVIP[0];}
     788              : 
     789              :         /// returns all ips of scv as they appear in scv loop
     790            0 :                 const MathVector<dim>* scv_local_ips() const {return &m_vLocSCVIP[0];}
     791              : 
     792              :         protected:
     793              :                 std::vector<MathVector<worldDim> > m_vGlobSCVFIP;
     794              :                 std::vector<MathVector<dim> > m_vLocSCVFIP;
     795              :                 std::vector<MathVector<worldDim> > m_vGlobSCVIP;
     796              :                 std::vector<MathVector<dim> > m_vLocSCVIP;
     797              : 
     798              :         protected:
     799            0 :                 void copy_local_corners(SCVF& scvf)
     800              :                 {
     801            0 :                         for(size_t i = 0; i < scvf.num_corners(); ++i)
     802              :                         {
     803            0 :                                 const size_t dim = scvf.m_midId[i].dim;
     804            0 :                                 const size_t id = scvf.m_midId[i].id;
     805              :                                 scvf.m_vLocPos[i] = m_locMid[dim][id];
     806              :                         }
     807            0 :                 }
     808              : 
     809            0 :                 void copy_global_corners(SCVF& scvf)
     810              :                 {
     811            0 :                         for(size_t i = 0; i < scvf.num_corners(); ++i)
     812              :                         {
     813            0 :                                 const size_t dim = scvf.m_midId[i].dim;
     814            0 :                                 const size_t id = scvf.m_midId[i].id;
     815              :                                 scvf.m_vGloPos[i] = m_gloMid[dim][id];
     816              :                         }
     817            0 :                 }
     818              : 
     819            0 :                 void copy_local_corners(SCV& scv)
     820              :                 {
     821            0 :                         for(size_t i = 0; i < scv.num_corners(); ++i)
     822              :                         {
     823            0 :                                 const size_t dim_ = scv.m_midId[i].dim;
     824            0 :                                 const size_t id = scv.m_midId[i].id;
     825              :                                 UG_ASSERT(dim_ <= (size_t)dim, "Dimension wrong");
     826              :                                 UG_ASSERT(id < m_locMid[dim_].size(), "id " << id << " in dim="
     827              :                                           <<dim_<<" wrong. (size is "<< m_locMid[dim_].size()<<")\n");
     828              :                                 scv.m_vLocPos[i] = m_locMid[dim_][id];
     829              :                         }
     830            0 :                 }
     831              : 
     832            0 :                 void copy_global_corners(SCV& scv)
     833              :                 {
     834            0 :                         for(size_t i = 0; i < scv.num_corners(); ++i)
     835              :                         {
     836            0 :                                 const size_t dim_ = scv.m_midId[i].dim;
     837            0 :                                 const size_t id = scv.m_midId[i].id;
     838              :                                 UG_ASSERT(dim_ <= (size_t)dim, "Dimension wrong");
     839              :                                 UG_ASSERT(id < m_gloMid[dim_].size(), "id " << id << " in dim="
     840              :                                           <<dim_<<" wrong. (size is "<< m_gloMid[dim_].size()<<")\n");
     841              :                                 scv.m_vGloPos[i] = m_gloMid[dim_][id];
     842              :                         }
     843            0 :                 }
     844              : 
     845              :                 // i = number of side
     846            0 :                 void compute_side_midpoints(size_t i,
     847              :                                             MathVector<dim>& locSideMid,
     848              :                                             MathVector<worldDim>& gloSideMid)
     849              :                 {
     850              :                         if(dim>1)
     851              :                         {
     852            0 :                                 const size_t coID0 = m_rRefElem.id(2, i, 0, 0);
     853              :                                 locSideMid = m_locMid[0][coID0];
     854              :                                 gloSideMid = m_gloMid[0][coID0];
     855              : 
     856              :                                 // add corner coordinates of the corners of the geometric object
     857            0 :                                 for(size_t j = 1; j < m_rRefElem.num(2, i, 0); ++j)
     858              :                                 {
     859            0 :                                         const size_t coID = m_rRefElem.id(2, i, 0, j);
     860              :                                         locSideMid += m_locMid[0][coID];
     861              :                                         gloSideMid += m_gloMid[0][coID];
     862              :                                 }
     863              : 
     864              :                                 // scale for correct averaging
     865            0 :                                 locSideMid *= 1./(m_rRefElem.num(2, i, 0));
     866              :                                 gloSideMid *= 1./(m_rRefElem.num(2, i, 0));
     867              :                         }
     868            0 :                 }
     869              : 
     870              :                 // i, j, k, l = number nodes
     871            0 :                 void compute_side_midpoints(size_t i, size_t j, size_t k, size_t l,
     872              :                                                                         MathVector<dim>& locSideMid,
     873              :                                                                         MathVector<worldDim>& gloSideMid)
     874              :                 {
     875              :                         VecAdd(locSideMid, m_locMid[0][i], m_locMid[0][j], m_locMid[0][k], m_locMid[0][l]);
     876              :                         VecAdd(gloSideMid, m_gloMid[0][i], m_gloMid[0][j], m_gloMid[0][k], m_gloMid[0][l]);
     877              : 
     878              :                         // scale for correct averaging
     879              :                         locSideMid *= 0.25;
     880              :                         gloSideMid *= 0.25;
     881            0 :                 }
     882              : 
     883              :                 // i, j, k = number nodes
     884            0 :                 void compute_side_midpoints(size_t i, size_t j, size_t k,
     885              :                                                                         MathVector<dim>& locSideMid, MathVector<worldDim>& gloSideMid)
     886              :                 {
     887              :                         VecAdd(locSideMid, m_locMid[0][i], m_locMid[0][j], m_locMid[0][k]);
     888              :                         VecAdd(gloSideMid, m_gloMid[0][i], m_gloMid[0][j], m_gloMid[0][k]);
     889              : 
     890              :                         // scale for correct averaging
     891              :                         locSideMid *= 1./3.;
     892              :                         gloSideMid *= 1./3.;
     893            0 :                 }
     894              : 
     895              :                 // returns edgeID of child edge, that has corner co. i is the natural edge index
     896            0 :                 size_t get_child_edge_of_corner(size_t i, size_t co)
     897              :         {
     898            0 :                 for(size_t e = 0; e < m_vNatEdgeInfo[i].num_child_edges(); ++e)
     899              :                 {
     900              :                         const size_t childId = m_vNatEdgeInfo[i].child_edge(e);
     901            0 :                         if(m_vNewEdgeInfo[childId].from() == co)
     902            0 :                                 return childId;
     903            0 :                         if(m_vNewEdgeInfo[childId].to() == co)
     904            0 :                                 return childId;
     905              :                 }
     906              :                 return -1;
     907              :         }
     908              : 
     909              :         private:
     910              :                 struct NewEdgeInfo
     911              :                 {
     912              :                         friend class DimHFV1Geometry<TDim, TWorldDim>;
     913              :                 public:
     914            0 :                         NewEdgeInfo() : m_from(-1), m_to(-1){}
     915            0 :             size_t from() const {return m_from;}
     916            0 :             size_t to() const {return m_to;}
     917              :                 private:
     918              :                         size_t m_from;
     919              :                         size_t m_to;
     920              :                 };
     921              : 
     922              :         struct NatEdgeInfo
     923              :         {
     924              :                 friend class DimHFV1Geometry<TDim, TWorldDim>;
     925              :             public:
     926            0 :                 NatEdgeInfo() : nodeId(-1), numChildEdges(0) {for(size_t i=0; i<2; ++i) childEdge[i] = -1;}
     927            0 :                 bool is_hanging() const {return numChildEdges == 2;}
     928            0 :                 size_t node_id() const {UG_ASSERT(is_hanging(), "Should only be called, if edge is hanging."); return nodeId;}
     929            0 :                 size_t num_child_edges() const {return numChildEdges;}
     930            0 :                 size_t child_edge(size_t i) const {UG_ASSERT(i < num_child_edges(), "Wrong id."); return childEdge[i];}
     931              : 
     932              :             private:
     933              :                 size_t nodeId;
     934              :                 size_t numChildEdges;
     935              :                 size_t childEdge[2];
     936              :         };
     937              : 
     938              :     //  help array: maps NaturalEdge -> NodeOnEdge (-1 if no node on edge)
     939              :         std::vector<NatEdgeInfo> m_vNatEdgeInfo;
     940              :         std::vector<NewEdgeInfo> m_vNewEdgeInfo;
     941              : 
     942              :         private:
     943              :         ///     pointer to current element
     944              :                 GridObject* m_pElem;
     945              :                 
     946              :         ///     current reference object id
     947              :                 ReferenceObjectID m_roid;
     948              : 
     949              :                 std::vector<MathVector<dim> > m_locMid[dim+1];
     950              :                 std::vector<MathVector<worldDim> > m_gloMid[dim+1];
     951              : 
     952              :         //      SubControlVolumeFaces
     953              :                 std::vector<SCVF> m_vSCVF;
     954              : 
     955              :         //      SubControlVolumes
     956              :                 std::vector<SCV> m_vSCV;
     957              : 
     958              :         //      number of shape functions
     959              :                 size_t m_numSh;
     960              : 
     961              :         /// reference element
     962              :                 DimReferenceElement<dim> m_rRefElem;
     963              : 
     964              :         /// reference mapping
     965              :                 DimReferenceMapping<dim, worldDim>* m_rMapping;
     966              :                 
     967              : };
     968              : 
     969              : 
     970              : ////////////////////////////////////////////////////////////////////////////////
     971              : // Hanging FV1 Manifold Geometry
     972              : ////////////////////////////////////////////////////////////////////////////////
     973              : 
     974              : template <typename TElem, int TWorldDim>
     975              : class HFV1ManifoldGeometry
     976              : {
     977              :         public:
     978              :         //      type of element
     979              :                 typedef TElem elem_type;
     980              : 
     981              :         //      type of reference element
     982              :                 typedef typename reference_element_traits<TElem>::reference_element_type ref_elem_type;
     983              : 
     984              :         public:
     985              :         //      order
     986              :                 static const int order = 1;
     987              : 
     988              :         // number of natural bfs (eq. of SCV)
     989              :                 static const size_t m_numNaturalBF = ref_elem_type::numCorners;
     990              : 
     991              :         // number of natural boundary face sides (eq. of SCVF)
     992              :                 static const size_t m_numNaturalBFS = ref_elem_type::numEdges;
     993              : 
     994              :         //      dimension of reference element
     995              :                 static const int dim = ref_elem_type::dim;
     996              : 
     997              :         //      dimension of world
     998              :                 static const int worldDim = TWorldDim;
     999              : 
    1000              :         //      type of BoundaryFaces
    1001              :                 typedef typename hfv1_traits<ref_elem_type, dim>::scv_type bf_type;
    1002              : 
    1003              :         //      Hanging node flag: this geometry supports hanging nodes
    1004              :                 static const bool usesHangingNodes = true;
    1005              : 
    1006              :         /// flag indicating if local data may change
    1007              :                 static const bool staticLocalData = true;
    1008              : 
    1009              :         protected:
    1010              :                 struct MidID
    1011              :                 {
    1012            0 :                                 MidID() : dim(0), id(0) {};
    1013            0 :                                 MidID(size_t dim_, size_t id_) : dim(dim_), id(id_) {};
    1014              :                                 size_t dim;
    1015              :                                 size_t id;
    1016              :                 };
    1017              : 
    1018              :         public:
    1019            0 :                 class BF
    1020              :                 {
    1021              :                         private:
    1022              :                         //      let outer class access private members
    1023              :                                 friend class HFV1ManifoldGeometry<TElem, TWorldDim>;
    1024              : 
    1025              :                         //      number of integration points
    1026              :                                 static const size_t m_numIP = 1;
    1027              : 
    1028              :                         //      max number of corners of bf
    1029              :                                 static const size_t numCorners = hfv1_traits<ref_elem_type, dim>::MaxNumCornersOfSCV;
    1030              : 
    1031              :                         public:
    1032            0 :                                 BF() {};
    1033              : 
    1034              :                         /// node id that this bf is associated to
    1035            0 :                                 inline size_t node_id() const {return nodeId;}
    1036              : 
    1037              :                         /// number of integration points
    1038            0 :                                 inline size_t num_ip() const {return m_numIP;}
    1039              : 
    1040              :                         /// local integration point of scvf
    1041            0 :                                 inline const MathVector<dim>& local_ip() const //{return localIP;}
    1042            0 :                                 {return m_vLocPos[0];}  // <-- always the vertex
    1043              : 
    1044              :                         /// global integration point of scvf
    1045            0 :                                 inline const MathVector<worldDim>& global_ip() const //{return globalIP;}
    1046            0 :                                 {return m_vGloPos[0];}  // <-- here too
    1047              : 
    1048              :                         /// volume of bf
    1049            0 :                                 inline number volume() const {return vol;}
    1050              : 
    1051              :                         /// number of corners, that bound the bf
    1052            0 :                                 inline size_t num_corners() const {return numCorners;}
    1053              : 
    1054              :                         /// return local position of corner number i
    1055            0 :                                 inline const MathVector<dim>& local_corner(size_t i) const
    1056            0 :                                         {UG_ASSERT(i < num_corners(), "Invalid index."); return m_vLocPos[i];}
    1057              : 
    1058              :                         /// return global position of corner number i
    1059            0 :                                 inline const MathVector<worldDim>& global_corner(size_t i) const
    1060            0 :                                         {UG_ASSERT(i < num_corners(), "Invalid index."); return m_vGloPos[i];}
    1061              : 
    1062              :                         /// number of shape functions
    1063            0 :                                 inline size_t num_sh() const {return vShape.size();}
    1064              : 
    1065              :                         /// value of shape function i in integration point
    1066            0 :                                 inline number shape(size_t i, size_t ip) const
    1067            0 :                                         {UG_ASSERT(ip < num_ip(), "Invalid index"); return vShape[i];}
    1068              : 
    1069              :                         private:
    1070              :                                 size_t nodeId;                                                                          // id of associated node
    1071              : 
    1072              :                                 // CORNERS: ordering is:
    1073              :                                 // 1D: corner, centerOfElement
    1074              :                                 // 2D: corner, side one, centerOfElement, side two
    1075              :                                 MathVector<dim> m_vLocPos[numCorners];                    // local position of node
    1076              :                                 MathVector<worldDim> m_vGloPos[numCorners];       // global position of node
    1077              : 
    1078              :                                 //IPs & shapes
    1079              :                                 MathVector<dim> localIP; // local integration point
    1080              :                                 MathVector<worldDim> globalIP; // global integration point
    1081              :                                 std::vector<number> vShape; // shapes at ip
    1082              : 
    1083              :                                 number vol;
    1084              :                 };
    1085              : 
    1086              :         protected:
    1087              :                 std::vector<MathVector<dim> > m_vLocBFIP;
    1088              :                 std::vector<MathVector<worldDim> > m_vGlobBFIP;
    1089              : 
    1090              :         public:
    1091              :         /// constructor
    1092              :                 HFV1ManifoldGeometry();
    1093              : 
    1094              :         ///     update data for given element
    1095              :                 void update(GridObject* elem, const MathVector<worldDim>* vCornerCoords,
    1096              :                             const ISubsetHandler* ish = NULL);
    1097              : 
    1098              :         /// print information about hfvg to log
    1099              :                 void print();
    1100              : /*
    1101              :         /// get vector of corners for current element
    1102              :                 const MathVector<worldDim>* corners() const {return m_gloMid[0];}
    1103              : */
    1104              :         /// number of BoundaryFaces
    1105            0 :                 inline size_t num_bf() const {return m_vBF.size();}
    1106              : 
    1107              :         /// const access to Boundary Face number i
    1108            0 :                 inline const BF& bf(size_t i) const
    1109            0 :                         {UG_ASSERT(i < num_bf(), "Invalid Index."); return m_vBF[i];}
    1110              : 
    1111              :         /// returns all ips of scvf as they appear in scv loop
    1112            0 :                 const MathVector<worldDim>* bf_global_ips() const {return &m_vGlobBFIP[0];}
    1113              : 
    1114              :         /// returns number of all scvf ips
    1115            0 :                 size_t num_bf_global_ips() const {return m_vGlobBFIP.size();}
    1116              : 
    1117              :         /// returns all ips of scvf as they appear in scv loop
    1118            0 :                 const MathVector<dim>* bf_local_ips() const {return &m_vLocBFIP[0];}
    1119              : 
    1120              :         /// returns number of all scvf ips
    1121            0 :                 size_t num_bf_local_ips() const {return m_vLocBFIP.size();}
    1122              : 
    1123              :         protected:
    1124            0 :                 void compute_side_midpoints(MathVector<dim>& locSideMid,
    1125              :                                                                    MathVector<worldDim>& gloSideMid)
    1126              :                 {
    1127              :                         locSideMid = m_locMid[0][0];
    1128              :                         gloSideMid = m_gloMid[0][0];
    1129              : 
    1130              :                         // add corner coordinates of the corners of the geometric object
    1131            0 :                         for (size_t j = 1; j < m_numNaturalBF; ++j)
    1132              :                         {
    1133              :                                 locSideMid += m_locMid[0][j];
    1134              :                                 gloSideMid += m_gloMid[0][j];
    1135              :                         }
    1136              : 
    1137              :                         // scale for correct averaging
    1138              :                         locSideMid /= m_numNaturalBF;
    1139              :                         gloSideMid /= m_numNaturalBF;
    1140            0 :                 }
    1141              : 
    1142              :                 // i, j, k, l = number nodes
    1143            0 :                 void compute_side_midpoints(size_t i, size_t j, size_t k, size_t l,
    1144              :                                                                         MathVector<dim>& locSideMid,
    1145              :                                                                         MathVector<worldDim>& gloSideMid)
    1146              :                 {
    1147              :                         VecAdd(locSideMid, m_locMid[0][i], m_locMid[0][j], m_locMid[0][k], m_locMid[0][l]);
    1148              :                         VecAdd(gloSideMid, m_gloMid[0][i], m_gloMid[0][j], m_gloMid[0][k], m_gloMid[0][l]);
    1149              : 
    1150              :                         // scale for correct averaging
    1151              :                         locSideMid *= 0.25;
    1152              :                         gloSideMid *= 0.25;
    1153            0 :                 }
    1154              : 
    1155              :                 // i, j, k = number nodes
    1156            0 :                 void compute_side_midpoints(size_t i, size_t j, size_t k,
    1157              :                                                                         MathVector<dim>& locSideMid, MathVector<worldDim>& gloSideMid)
    1158              :                 {
    1159              :                         VecAdd(locSideMid, m_locMid[0][i], m_locMid[0][j], m_locMid[0][k]);
    1160              :                         VecAdd(gloSideMid, m_gloMid[0][i], m_gloMid[0][j], m_gloMid[0][k]);
    1161              : 
    1162              :                         // scale for correct averaging
    1163              :                         locSideMid *= 1./3.;
    1164              :                         gloSideMid *= 1./3.;
    1165            0 :                 }
    1166              : 
    1167              :         private:
    1168              :                 struct NewEdgeInfo
    1169              :                 {
    1170              :                         friend class HFV1ManifoldGeometry<TElem, TWorldDim>;
    1171              : 
    1172              :                         public:
    1173            0 :                                 NewEdgeInfo() : m_from(-1), m_to(-1){}
    1174            0 :                                 size_t from() const {return m_from;}
    1175            0 :                                 size_t to() const {return m_to;}
    1176              :                         private:
    1177              :                                 size_t m_from;
    1178              :                                 size_t m_to;
    1179              :                 };
    1180              : 
    1181              :                 struct NatEdgeInfo
    1182              :                 {
    1183              :                         friend class HFV1ManifoldGeometry<TElem, TWorldDim>;
    1184              :                         public:
    1185            0 :                                 NatEdgeInfo() : nodeId(-1), numChildEdges(0) {for(size_t i=0; i<2; ++i) childEdge[i] = -1;}
    1186            0 :                                 bool is_hanging() const {return numChildEdges == 2;}
    1187            0 :                                 size_t node_id() const {UG_ASSERT(is_hanging(), "Should only be called, if edge is hanging."); return nodeId;}
    1188            0 :                                 size_t num_child_edges() const {return numChildEdges;}
    1189            0 :                                 size_t child_edge(size_t i) const {UG_ASSERT(i < num_child_edges(), "Wrong id."); return childEdge[i];}
    1190              : 
    1191              :                         private:
    1192              :                                 size_t nodeId;
    1193              :                                 size_t numChildEdges;
    1194              :                                 size_t childEdge[2];
    1195              :                 };
    1196              : 
    1197              :         //  help array: maps NaturalEdge -> NodeOnEdge (-1 if no node on edge)
    1198              :                 std::vector<NatEdgeInfo> m_vNatEdgeInfo;
    1199              :                 std::vector<NewEdgeInfo> m_vNewEdgeInfo;
    1200              : 
    1201              :         private:
    1202              :         //      pointer to current element
    1203              :                 GridObject* m_pElem;
    1204              : 
    1205              :         //      local and global geom object midpoints for each dimension
    1206              :                 std::vector<MathVector<dim> > m_locMid[dim+1];
    1207              :                 std::vector<MathVector<worldDim> > m_gloMid[dim+1];
    1208              : 
    1209              :         //      BndFaces
    1210              :                 std::vector<BF> m_vBF;
    1211              : 
    1212              :         //      Reference Mapping
    1213              :                 ReferenceMapping<ref_elem_type, worldDim> m_rMapping;
    1214              : 
    1215              :         //      Reference Element
    1216              :                 const ref_elem_type& m_rRefElem;
    1217              : };
    1218              : 
    1219              : 
    1220              : }
    1221              : 
    1222              : #endif /* __H__UG__LIB_DISC__SPATIAL_DISC__DISC_HELPER__HANGING_FINITE_VOLUME_GEOMETRY__ */
        

Generated by: LCOV version 2.0-1