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

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2013-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              : 
      34              : #include "common/util/provider.h"
      35              : #include "fvho_geom.h"
      36              : #include "lib_disc/reference_element/reference_element.h"
      37              : #include "lib_disc/quadrature/quadrature_provider.h"
      38              : #include "lib_algebra/common/operations_vec.h"
      39              : #include <math.h>       /* pow */
      40              : 
      41              : namespace ug{
      42              : 
      43              : 
      44              : /**
      45              :  * \tparam      dim                     dimension of coordinates
      46              :  * \tparam      TRefElem        Reference element type
      47              :  * \tparam      maxMid          Maximum number of elements for all dimensions
      48              :  */
      49              : template <int dim, typename TRefElem, int maxMid>
      50            0 : static void ComputeMidPoints(const TRefElem& rRefElem,
      51              :                              const MathVector<dim> vCorner[],
      52              :                              MathVector<dim> vvMid[][maxMid])
      53              : {
      54              : //      compute local midpoints for all geometric objects with  0 < d <= dim
      55            0 :         for(int d = 1; d <= dim; ++d)
      56              :         {
      57              :         //      loop geometric objects of dimension d
      58            0 :                 for(size_t i = 0; i < rRefElem.num(d); ++i)
      59              :                 {
      60              :                 //      set first node
      61            0 :                         const size_t coID0 = rRefElem.id(d, i, 0, 0);
      62            0 :                         vvMid[d][i] = vCorner[coID0];
      63              : 
      64              :                 //      add corner coordinates of the corners of the geometric object
      65            0 :                         for(size_t j = 1; j < rRefElem.num(d, i, 0); ++j)
      66              :                         {
      67            0 :                                 const size_t coID = rRefElem.id(d, i, 0, j);
      68            0 :                                 vvMid[d][i] += vCorner[coID];
      69              :                         }
      70              : 
      71              :                 //      scale for correct averaging
      72            0 :                         vvMid[d][i] *= 1./(rRefElem.num(d, i, 0));
      73              :                 }
      74              :         }
      75              : 
      76              :         // for PYRAMIDS: add midpoints of imaginary faces, edges and volumes
      77              :         // resulting from the division into two tetrahedra alongside x==y
      78            0 :         if (rRefElem.roid() == ROID_PYRAMID)
      79              :         {
      80            0 :                 UG_THROW("Pyramid FV geometries are currently implemented incorrectly."
      81              :                         " Please contact Martin Stepniewski if you see this error. ");
      82              : 
      83              :                 // diagonal 2->0, diagonal 0->2
      84              :                 VecScaleAdd(vvMid[1][rRefElem.num(1)], 0.5, vCorner[2], 0.5, vCorner[0]);
      85              :                 VecScaleAdd(vvMid[1][rRefElem.num(1)+1], 0.5, vCorner[0], 0.5, vCorner[2]);
      86              : 
      87              :                 // subface 0,1,2; subface 0,2,3; face 0,4,2; face 0,2,4
      88              :                 vvMid[2][rRefElem.num(2)] = vCorner[0];
      89              :                 vvMid[2][rRefElem.num(2)] += vCorner[1];
      90              :                 vvMid[2][rRefElem.num(2)] += vCorner[2];
      91              :                 vvMid[2][rRefElem.num(2)] *= 1.0/3.0;
      92              : 
      93              :                 vvMid[2][rRefElem.num(2)+1] = vCorner[0];
      94              :                 vvMid[2][rRefElem.num(2)+1] += vCorner[2];
      95              :                 vvMid[2][rRefElem.num(2)+1] += vCorner[3];
      96              :                 vvMid[2][rRefElem.num(2)+1] *= 1.0/3.0;
      97              : 
      98              :                 vvMid[2][rRefElem.num(2)+2] = vCorner[0];
      99              :                 vvMid[2][rRefElem.num(2)+2] += vCorner[4];
     100              :                 vvMid[2][rRefElem.num(2)+2] += vCorner[2];
     101              :                 vvMid[2][rRefElem.num(2)+2] *= 1.0/3.0;
     102              : 
     103              :                 vvMid[2][rRefElem.num(2)+3] = vCorner[0];
     104              :                 vvMid[2][rRefElem.num(2)+3] += vCorner[2];
     105              :                 vvMid[2][rRefElem.num(2)+3] += vCorner[4];
     106              :                 vvMid[2][rRefElem.num(2)+3] *= 1.0/3.0;
     107              : 
     108              :                 // subvolume 0,1,2,4; subvolume 0,2,3,4
     109              : 
     110              :                 vvMid[3][rRefElem.num(3)] = vCorner[0];
     111              :                 vvMid[3][rRefElem.num(3)] += vCorner[1];
     112              :                 vvMid[3][rRefElem.num(3)] += vCorner[2];
     113              :                 vvMid[3][rRefElem.num(3)] += vCorner[4];
     114              :                 vvMid[3][rRefElem.num(3)] *= 0.25;
     115              : 
     116              :                 vvMid[3][rRefElem.num(3)+1] = vCorner[0];
     117              :                 vvMid[3][rRefElem.num(3)+1] += vCorner[2];
     118              :                 vvMid[3][rRefElem.num(3)+1] += vCorner[3];
     119              :                 vvMid[3][rRefElem.num(3)+1] += vCorner[4];
     120              :                 vvMid[3][rRefElem.num(3)+1] *= 0.25;
     121              :         }
     122            0 : }
     123              : 
     124              : /**
     125              :  * \param[in]   i               indicates that scvf corresponds to i'th edge of ref elem
     126              :  */
     127              : template <typename TRefElem>
     128            0 : static void ComputeSCVFMidID(const TRefElem& rRefElem,
     129              :                                    MidID vMidID[], int i)
     130              : {
     131              :         static const int dim = TRefElem::dim;
     132              : 
     133            0 :         if (rRefElem.roid() != ROID_PYRAMID)
     134              :         {
     135              :                 //      set mid ids
     136              :                 {
     137              :                         //      start at edge midpoint
     138            0 :                         vMidID[0] = MidID(1,i);
     139              : 
     140              :                         //      loop up dimension
     141              :                         if(dim == 2)
     142              :                         {
     143            0 :                                 vMidID[1] = MidID(dim, 0); // center of element
     144              :                         }
     145              :                         else if (dim == 3)
     146              :                         {
     147            0 :                                 vMidID[1] = MidID(2, rRefElem.id(1, i, 2, 0)); // side 0
     148            0 :                                 vMidID[2] = MidID(dim, 0); // center of element
     149            0 :                                 vMidID[3] = MidID(2, rRefElem.id(1, i, 2, 1)); // side 1
     150              :                         }
     151              :                 }
     152              :         }
     153              :         // pyramid here
     154              :         else
     155              :         {
     156            0 :                 switch (i)
     157              :                 {
     158              :                         // scvf of edge 0
     159            0 :                         case 0: vMidID[0] = MidID(1,0); // edge 0
     160            0 :                                         vMidID[1] = MidID(2,5); // subface 0/0
     161            0 :                                         vMidID[2] = MidID(3,1); // subvolume 0/0
     162            0 :                                         vMidID[3] = MidID(2,1); // face 1
     163            0 :                                         break;
     164              :                         // scvf of edge 1
     165            0 :                         case 1: vMidID[0] = MidID(1,1); // edge 1
     166            0 :                                         vMidID[1] = MidID(2,5); // subface 0/0
     167            0 :                                         vMidID[2] = MidID(3,1); // subvolume 0/0
     168            0 :                                         vMidID[3] = MidID(2,2); // face 2
     169            0 :                                         break;
     170              :                         // scvf of diagonal 2->0
     171            0 :                         case 2: vMidID[0] = MidID(1,8); // diagonal 2->0
     172            0 :                                         vMidID[1] = MidID(2,5); // subface 0/0
     173            0 :                                         vMidID[2] = MidID(3,1); // subvolume 0/0
     174            0 :                                         vMidID[3] = MidID(2,7); // face 0,4,2
     175            0 :                                         break;
     176              :                         // scvf of edge 4 in subvolume 0/0
     177            0 :                         case 3: vMidID[0] = MidID(1,4); // edge 4
     178            0 :                                         vMidID[1] = MidID(2,1); // face 1
     179            0 :                                         vMidID[2] = MidID(3,1); // subvolume 0/0
     180            0 :                                         vMidID[3] = MidID(2,7); // face 0,4,2
     181            0 :                                         break;
     182              :                         // scvf of edge 5
     183            0 :                         case 4: vMidID[0] = MidID(1,5); // edge 5
     184            0 :                                         vMidID[1] = MidID(2,2); // face 2
     185            0 :                                         vMidID[2] = MidID(3,1); // subvolume 0/0
     186            0 :                                         vMidID[3] = MidID(2,1); // face 1
     187            0 :                                         break;
     188              :                         // scvf of edge 6 in subvolume 0/0
     189            0 :                         case 5: vMidID[0] = MidID(1,6); // edge 6
     190            0 :                                         vMidID[1] = MidID(2,7); // face 0,4,2
     191            0 :                                         vMidID[2] = MidID(3,1); // subvolume 0/0
     192            0 :                                         vMidID[3] = MidID(2,2); // face 2
     193            0 :                                         break;
     194              :                         // edge 0->2
     195            0 :                         case 6: vMidID[0] = MidID(1,9); // edge 0->2
     196            0 :                                         vMidID[1] = MidID(2,6); // subface 1/0
     197            0 :                                         vMidID[2] = MidID(3,2); // subvolume 1/0
     198            0 :                                         vMidID[3] = MidID(2,8); // face 0,2,4
     199            0 :                                         break;
     200              :                         // scvf of edge 2
     201            0 :                         case 7: vMidID[0] = MidID(1,2); // edge 2
     202            0 :                                         vMidID[1] = MidID(2,6); // subface 1/0
     203            0 :                                         vMidID[2] = MidID(3,2); // subvolume 1/0
     204            0 :                                         vMidID[3] = MidID(2,3); // face 3
     205            0 :                                         break;
     206              :                         // scvf of edge 3
     207            0 :                         case 8: vMidID[0] = MidID(1,3); // edge 3
     208            0 :                                         vMidID[1] = MidID(2,6); // subface 1/0
     209            0 :                                         vMidID[2] = MidID(3,2); // subvolume 1/0
     210            0 :                                         vMidID[3] = MidID(2,4); // face 4
     211            0 :                                         break;
     212              :                         // scvf of edge 4 in subvolume 1/0
     213            0 :                         case 9: vMidID[0] = MidID(1,4); // edge 4
     214            0 :                                         vMidID[1] = MidID(2,8); // face 0,2,4
     215            0 :                                         vMidID[2] = MidID(3,2); // subvolume 1/0
     216            0 :                                         vMidID[3] = MidID(2,4); // face 4
     217            0 :                                         break;
     218              :                         // scvf of edge 6 in subvolume 1/0
     219            0 :                         case 10:vMidID[0] = MidID(1,6); // edge 6
     220            0 :                                         vMidID[1] = MidID(2,3); // face 3
     221            0 :                                         vMidID[2] = MidID(3,2); // subvolume 1/0
     222            0 :                                         vMidID[1] = MidID(2,8); // face 0,2,4
     223            0 :                                         break;
     224              :                         // scvf of edge 7
     225            0 :                         case 11:vMidID[0] = MidID(1,7); // edge 7
     226            0 :                                         vMidID[3] = MidID(2,4); // face 4
     227            0 :                                         vMidID[2] = MidID(3,2); // subvolume 1/0
     228            0 :                                         vMidID[1] = MidID(2,3); // face 3
     229            0 :                                         break;
     230            0 :                         default:UG_THROW("Pyramid only has 12 SCVFs (no. 0-11), but requested no. " << i << ".");
     231              :                                         break;
     232              :                 }
     233              :         }
     234            0 : }
     235              : 
     236              : /**
     237              :  * \param[in]   i               indicates that scvf corresponds to i'th corner of ref elem
     238              :  */
     239              : template <typename TRefElem>
     240            0 : static void ComputeSCVMidID(const TRefElem& rRefElem,
     241              :                             MidID vMidID[], int i)
     242              : {
     243              :         static const int dim = TRefElem::dim;
     244              : 
     245            0 :         if (rRefElem.roid() != ROID_PYRAMID)
     246              :         {
     247              :                 if(dim == 1)
     248              :                 {
     249            0 :                         vMidID[0] = MidID(0, i); // set node as corner of scv
     250            0 :                         vMidID[1] = MidID(dim, 0);      // center of element
     251              :                 }
     252              :                 else if(dim == 2)
     253              :                 {
     254            0 :                         vMidID[0] = MidID(0, i); // set node as corner of scv
     255            0 :                         vMidID[1] = MidID(1, rRefElem.id(0, i, 1, 0)); // edge 1
     256            0 :                         vMidID[2] = MidID(dim, 0);      // center of element
     257            0 :                         vMidID[3] = MidID(1, rRefElem.id(0, i, 1, 1)); // edge 2
     258              :                 }
     259              :                 else if(dim == 3)
     260              :                 {
     261            0 :                         vMidID[0] = MidID(0, i); // set node as corner of scv
     262            0 :                         vMidID[1] = MidID(1, rRefElem.id(0, i, 1, 1)); // edge 1
     263            0 :                         vMidID[2] = MidID(2, rRefElem.id(0, i, 2, 0)); // face 0
     264            0 :                         vMidID[3] = MidID(1, rRefElem.id(0, i, 1, 0)); // edge 0
     265            0 :                         vMidID[4] = MidID(1, rRefElem.id(0, i, 1, 2)); // edge 2
     266            0 :                         vMidID[5] = MidID(2, rRefElem.id(0, i, 2, 2)); // face 2
     267            0 :                         vMidID[6] = MidID(dim, 0);      // center of element
     268            0 :                         vMidID[7] = MidID(2, rRefElem.id(0, i, 2, 1)); // face 1
     269              :                 }
     270              :                 else {UG_THROW("Dimension higher that 3 not implemented.");}
     271              :         }
     272              :         // pyramid here
     273              :         else
     274              :         {
     275            0 :                 switch (i)
     276              :                 {
     277              :                         // scv of corner 0 in subvolume 0/0
     278            0 :                         case 0: vMidID[0] = MidID(0,0); // corner 0
     279            0 :                                         vMidID[1] = MidID(1,0); // edge 0
     280            0 :                                         vMidID[2] = MidID(2,5); // subface 0/0
     281            0 :                                         vMidID[3] = MidID(1,8); // edge 2->0
     282            0 :                                         vMidID[4] = MidID(1,4); // edge 4
     283            0 :                                         vMidID[5] = MidID(2,1); // face 1
     284            0 :                                         vMidID[6] = MidID(3,1); // subvolume 0/0
     285            0 :                                         vMidID[7] = MidID(2,7); // face 0,4,2
     286            0 :                                         break;
     287              :                         // scv of corner 1
     288            0 :                         case 1: vMidID[0] = MidID(0,1); // corner 1
     289            0 :                                         vMidID[1] = MidID(1,1); // edge 1
     290            0 :                                         vMidID[2] = MidID(2,5); // subface 0/0
     291            0 :                                         vMidID[3] = MidID(1,0); // edge 0
     292            0 :                                         vMidID[4] = MidID(1,5); // edge 5
     293            0 :                                         vMidID[5] = MidID(2,2); // face 2
     294            0 :                                         vMidID[6] = MidID(3,1); // subvolume 0/0
     295            0 :                                         vMidID[7] = MidID(2,1); // face 1
     296            0 :                                         break;
     297              :                         // scv of corner 2 in subvolume 0/0
     298            0 :                         case 2: vMidID[0] = MidID(0,2); // corner 2
     299            0 :                                         vMidID[1] = MidID(1,8); // edge 2->0
     300            0 :                                         vMidID[2] = MidID(2,5); // subface 0/0
     301            0 :                                         vMidID[3] = MidID(1,1); // edge 1
     302            0 :                                         vMidID[4] = MidID(1,6); // edge 6
     303            0 :                                         vMidID[5] = MidID(2,7); // face 0,4,2
     304            0 :                                         vMidID[6] = MidID(3,1); // subvolume 0/0
     305            0 :                                         vMidID[7] = MidID(2,2); // face 2
     306            0 :                                         break;
     307              :                         // scv of corner 4 in subvolume 0/0
     308            0 :                         case 3: vMidID[0] = MidID(0,4); // corner 4
     309            0 :                                         vMidID[1] = MidID(1,5); // edge 5
     310            0 :                                         vMidID[2] = MidID(2,1); // face 1
     311            0 :                                         vMidID[3] = MidID(1,4); // edge 4
     312            0 :                                         vMidID[4] = MidID(1,6); // edge 6
     313            0 :                                         vMidID[5] = MidID(2,2); // face 2
     314            0 :                                         vMidID[6] = MidID(3,1); // subvolume 0/0
     315            0 :                                         vMidID[7] = MidID(2,7); // face 0,4,2
     316            0 :                                         break;
     317              :                         // scv of corner 0 in subvolume 1/0
     318            0 :                         case 4: vMidID[0] = MidID(0,0); // corner 0
     319            0 :                                         vMidID[1] = MidID(1,9); // edge 0->2
     320            0 :                                         vMidID[2] = MidID(2,6); // subface 1/0
     321            0 :                                         vMidID[3] = MidID(1,3); // edge 3
     322            0 :                                         vMidID[4] = MidID(1,4); // edge 4
     323            0 :                                         vMidID[5] = MidID(2,8); // face 0,2,4
     324            0 :                                         vMidID[6] = MidID(3,2); // subvolume 1/0
     325            0 :                                         vMidID[7] = MidID(2,4); // face 4
     326            0 :                                         break;
     327              :                         // scv of corner 2 in subvolume 1/0
     328            0 :                         case 5: vMidID[0] = MidID(0,2); // corner 2
     329            0 :                                         vMidID[1] = MidID(1,2); // edge 2
     330            0 :                                         vMidID[2] = MidID(2,6); // subface 1/0
     331            0 :                                         vMidID[3] = MidID(1,9); // edge 0->2
     332            0 :                                         vMidID[4] = MidID(1,6); // edge 6
     333            0 :                                         vMidID[5] = MidID(2,3); // face 3
     334            0 :                                         vMidID[6] = MidID(3,2); // subvolume 1/0
     335            0 :                                         vMidID[7] = MidID(2,8); // face 0,2,4
     336            0 :                                         break;
     337              :                         // scv of corner 3
     338            0 :                         case 6: vMidID[0] = MidID(0,3); // corner 3
     339            0 :                                         vMidID[1] = MidID(1,3); // edge 3
     340            0 :                                         vMidID[2] = MidID(2,6); // subface 1/0
     341            0 :                                         vMidID[3] = MidID(1,2); // edge 2
     342            0 :                                         vMidID[4] = MidID(1,7); // edge 7
     343            0 :                                         vMidID[5] = MidID(2,4); // face 4
     344            0 :                                         vMidID[6] = MidID(3,2); // subvolume 1/0
     345            0 :                                         vMidID[7] = MidID(2,3); // face 3
     346            0 :                                         break;
     347              :                         // scv of corner 4 in subvolume 1/0
     348            0 :                         case 7: vMidID[0] = MidID(0,4); // corner 4
     349            0 :                                         vMidID[1] = MidID(1,6); // edge 6
     350            0 :                                         vMidID[2] = MidID(2,8); // face 0,2,4
     351            0 :                                         vMidID[3] = MidID(1,4); // edge 4
     352            0 :                                         vMidID[4] = MidID(1,7); // edge 7
     353            0 :                                         vMidID[5] = MidID(2,3); // face 3
     354            0 :                                         vMidID[6] = MidID(3,2); // subvolume 1/0
     355            0 :                                         vMidID[7] = MidID(2,4); // face 4
     356            0 :                                         break;
     357            0 :                         default:UG_THROW("Pyramid only has 8 SCVs (no. 0-7), but requested no. " << i << ".");
     358              :                                         break;
     359              :                 }
     360              :         }
     361            0 : }
     362              : 
     363              : /**
     364              :  * \param[in]   i               indicates that scvf corresponds to i'th corner of ref elem
     365              :  */
     366              : template <typename TRefElem>
     367            0 : static void ComputeBFMidID(const TRefElem& rRefElem, int side,
     368              :                             MidID vMidID[], int co)
     369              : {
     370              :         static const int dim = TRefElem::dim;
     371              : 
     372            0 :         if (rRefElem.roid() != ROID_PYRAMID || side != 0)
     373              :         {
     374              :                 //      number of corners of side
     375            0 :                 const int coOfSide = rRefElem.num(dim-1, side, 0);
     376              : 
     377              :                 //      set mid ids
     378              :                 if(dim == 2)
     379              :                 {
     380            0 :                         vMidID[co%2] = MidID(0, rRefElem.id(1, side, 0, co)); // corner of side
     381            0 :                         vMidID[(co+1)%2] = MidID(1, side); // side midpoint
     382              :                 }
     383              :                 else if (dim == 3)
     384              :                 {
     385            0 :                         vMidID[0] = MidID(0, rRefElem.id(2, side, 0, co)); // corner of side
     386            0 :                         vMidID[1] = MidID(1, rRefElem.id(2, side, 1, co)); // edge co
     387            0 :                         vMidID[2] = MidID(2, side); // side midpoint
     388            0 :                         vMidID[3] = MidID(1, rRefElem.id(2, side, 1, (co -1 + coOfSide)%coOfSide)); // edge co-1
     389              :                 }
     390              :         }
     391              :         // bottom side of pyramid here
     392              :         else
     393              :         {
     394            0 :                 switch (co)
     395              :                 {
     396              :                         // bf of corner 0 in subface 0/0
     397            0 :                         case 0: vMidID[0] = MidID(0,0); // corner 0
     398            0 :                                         vMidID[1] = MidID(1,8); // edge 2->0
     399            0 :                                         vMidID[2] = MidID(2,5); // subface 0/0
     400            0 :                                         vMidID[3] = MidID(1,0); // edge 0
     401            0 :                                         break;
     402              :                         // bf of corner 1
     403            0 :                         case 1: vMidID[0] = MidID(0,1); // corner 1
     404            0 :                                         vMidID[1] = MidID(1,0); // edge 0
     405            0 :                                         vMidID[2] = MidID(2,5); // subface 0/0
     406            0 :                                         vMidID[3] = MidID(1,1); // edge 1
     407            0 :                                         break;
     408              :                         // bf of corner 2 in subvolume 0/0
     409            0 :                         case 2: vMidID[0] = MidID(0,2); // corner 2
     410            0 :                                         vMidID[1] = MidID(1,1); // edge 1
     411            0 :                                         vMidID[2] = MidID(2,5); // subface 0/0
     412            0 :                                         vMidID[3] = MidID(1,8); // edge 2->0
     413            0 :                                         break;
     414              :                         // bf of corner 0 in subvolume 1/0
     415            0 :                         case 3: vMidID[0] = MidID(0,0); // corner 0
     416            0 :                                         vMidID[1] = MidID(1,3); // edge 3
     417            0 :                                         vMidID[2] = MidID(2,6); // subface 1/0
     418            0 :                                         vMidID[3] = MidID(1,9); // edge 0->2
     419            0 :                                         break;
     420              :                         // bf of corner 2 in subvolume 1/0
     421            0 :                         case 4: vMidID[0] = MidID(0,2); // corner 2
     422            0 :                                         vMidID[1] = MidID(1,9); // edge 0->2
     423            0 :                                         vMidID[2] = MidID(2,6); // subface 1/0
     424            0 :                                         vMidID[3] = MidID(1,2); // edge 2
     425            0 :                                         break;
     426              :                         // bf of corner 3
     427            0 :                         case 5: vMidID[0] = MidID(0,3); // corner 3
     428            0 :                                         vMidID[1] = MidID(1,2); // edge 2
     429            0 :                                         vMidID[2] = MidID(2,6); // subface 1/0
     430            0 :                                         vMidID[3] = MidID(1,3); // edge 3
     431            0 :                                         break;
     432            0 :                         default:UG_THROW("Pyramid only has 6 BFs on bottom side (no. 0-5), but requested no. " << co << ".");
     433              :                                         break;
     434              :                 }
     435              :         }
     436            0 : }
     437              : 
     438              : template <int dim, int maxMid>
     439            0 : static void CopyCornerByMidID(MathVector<dim> vCorner[],
     440              :                               const MidID vMidID[],
     441              :                               MathVector<dim> vvMidPos[][maxMid],
     442              :                               const size_t numCo)
     443              : {
     444            0 :         for(size_t i = 0; i < numCo; ++i)
     445              :         {
     446            0 :                 const size_t d = vMidID[i].dim;
     447            0 :                 const size_t id = vMidID[i].id;
     448            0 :                 vCorner[i] = vvMidPos[d][id];
     449              :         }
     450            0 : }
     451              : 
     452              : template <int dim>
     453              : void ComputeMultiIndicesOfSubElement(std::vector<MathVector<dim, int> >* vvMultiIndex,
     454              :                                      bool* vIsBndElem,
     455              :                                      std::vector<int>* vElemBndSide,
     456              :                                      std::vector<size_t>* vIndex,
     457              :                                      ReferenceObjectID roid,
     458              :                                      int p);
     459              : 
     460              : template <>
     461            0 : void ComputeMultiIndicesOfSubElement<1>(std::vector<MathVector<1, int> >* vvMultiIndex,
     462              :                                         bool* vIsBndElem,
     463              :                                         std::vector<int>* vElemBndSide,
     464              :                                         std::vector<size_t>* vIndex,
     465              :                                         ReferenceObjectID roid,
     466              :                                         int p)
     467              : {
     468              : //      switch for roid
     469              :         size_t se = 0;
     470            0 :         switch(roid)
     471              :         {
     472              :                 case ROID_EDGE:
     473            0 :                         for(int i = 0; i < p; ++i)
     474              :                         {
     475            0 :                                 vvMultiIndex[se].resize(2);
     476              :                                 vvMultiIndex[se][0] = MathVector<1,int>(i);
     477            0 :                                 vvMultiIndex[se][1] = MathVector<1,int>(i+1);
     478              : 
     479              :                                 // reset bnd info
     480            0 :                                 vIsBndElem[se] = false;
     481            0 :                                 vElemBndSide[se].clear(); vElemBndSide[se].resize(3, -1);
     482              : 
     483            0 :                                 if(i==0)
     484              :                                 {
     485            0 :                                         vIsBndElem[se] = true;
     486            0 :                                         vElemBndSide[se][0] = 0;
     487              :                                 }
     488            0 :                                 if(i==p-1)
     489              :                                 {
     490            0 :                                         vIsBndElem[se] = true;
     491            0 :                                         vElemBndSide[se][1] = 1;
     492              :                                 }
     493            0 :                                 ++se;
     494              :                         }
     495              : 
     496              :                         {
     497            0 :                                 FlexLagrangeLSFS<ReferenceEdge> set(p);
     498            0 :                                 for(size_t s = 0; s < se; ++s)
     499              :                                 {
     500            0 :                                         vIndex[s].resize(vvMultiIndex[s].size());
     501            0 :                                         for(size_t i = 0; i < vvMultiIndex[s].size(); ++i)
     502              :                                         {
     503            0 :                                                 vIndex[s][i] = set.index(vvMultiIndex[s][i]);
     504              :                                         }
     505              :                                 }
     506            0 :                         }
     507              :                         break;
     508            0 :                 default: UG_THROW("ReferenceElement not found.");
     509              :         }
     510            0 : }
     511              : 
     512              : template <>
     513            0 : void ComputeMultiIndicesOfSubElement<2>(std::vector<MathVector<2, int> >* vvMultiIndex,
     514              :                                         bool* vIsBndElem,
     515              :                                         std::vector<int>* vElemBndSide,
     516              :                                         std::vector<size_t>* vIndex,
     517              :                                         ReferenceObjectID roid,
     518              :                                         int p)
     519              : {
     520              : //      switch for roid
     521              :         size_t se = 0;
     522            0 :         switch(roid)
     523              :         {
     524              :                 case ROID_TRIANGLE:
     525            0 :                         for(int j = 0; j < p; ++j) { // y -direction
     526            0 :                                 for(int i = 0; i < p - j; ++i) { // x - direction
     527            0 :                                         vvMultiIndex[se].resize(3);
     528              :                                         vvMultiIndex[se][0] = MathVector<2,int>(i  , j  );
     529            0 :                                         vvMultiIndex[se][1] = MathVector<2,int>(i+1, j  );
     530            0 :                                         vvMultiIndex[se][2] = MathVector<2,int>(i  , j+1);
     531              : 
     532              :                                         // reset bnd info
     533            0 :                                         vIsBndElem[se] = false;
     534            0 :                                         vElemBndSide[se].clear(); vElemBndSide[se].resize(3, -1);
     535              : 
     536            0 :                                         if(i==0) // left
     537              :                                         {
     538            0 :                                                 vIsBndElem[se] = true;
     539            0 :                                                 vElemBndSide[se][2] = 2;
     540              :                                         }
     541            0 :                                         if(j==0) // bottom
     542              :                                         {
     543            0 :                                                 vIsBndElem[se] = true;
     544            0 :                                                 vElemBndSide[se][0] = 0;
     545              :                                         }
     546            0 :                                         if(i+j==p-1) // diag
     547              :                                         {
     548            0 :                                                 vIsBndElem[se] = true;
     549            0 :                                                 vElemBndSide[se][1] = 1;
     550              :                                         }
     551            0 :                                         ++se;
     552              :                                 }
     553              :                         }
     554              : 
     555            0 :                         for(int j = 1; j <= p; ++j) {
     556            0 :                                 for(int i = 1; i <= p - j; ++i) {
     557            0 :                                         vvMultiIndex[se].resize(3);
     558              :                                         vvMultiIndex[se][0] = MathVector<2,int>(i  , j  );
     559            0 :                                         vvMultiIndex[se][1] = MathVector<2,int>(i-1, j  );
     560            0 :                                         vvMultiIndex[se][2] = MathVector<2,int>(i  , j-1);
     561              : 
     562              :                                         // reset bnd info
     563              :                                         // all inner elems
     564            0 :                                         vIsBndElem[se] = false;
     565            0 :                                         vElemBndSide[se].clear(); vElemBndSide[se].resize(3, -1);
     566            0 :                                         ++se;
     567              :                                 }
     568              :                         }
     569              : 
     570              :                         {
     571            0 :                                 FlexLagrangeLSFS<ReferenceTriangle> set(p);
     572            0 :                                 for(size_t s = 0; s < se; ++s)
     573              :                                 {
     574            0 :                                         vIndex[s].resize(vvMultiIndex[s].size());
     575            0 :                                         for(size_t i = 0; i < vvMultiIndex[s].size(); ++i)
     576              :                                         {
     577            0 :                                                 vIndex[s][i] = set.index(vvMultiIndex[s][i]);
     578              :                                         }
     579              :                                 }
     580            0 :                         }
     581              : 
     582            0 :                         break;
     583              :                 case ROID_QUADRILATERAL:
     584            0 :                         for(int j = 0; j < p; ++j) {
     585            0 :                                 for(int i = 0; i < p; ++i) {
     586            0 :                                         vvMultiIndex[se].resize(4);
     587              :                                         vvMultiIndex[se][0] = MathVector<2,int>(i  , j  );
     588            0 :                                         vvMultiIndex[se][1] = MathVector<2,int>(i+1, j  );
     589            0 :                                         vvMultiIndex[se][2] = MathVector<2,int>(i+1, j+1);
     590              :                                         vvMultiIndex[se][3] = MathVector<2,int>(i  , j+1);
     591              : 
     592              :                                         // reset bnd info
     593            0 :                                         vIsBndElem[se] = false;
     594            0 :                                         vElemBndSide[se].clear(); vElemBndSide[se].resize(4, -1);
     595              : 
     596            0 :                                         if(i==0) // left
     597              :                                         {
     598            0 :                                                 vIsBndElem[se] = true;
     599            0 :                                                 vElemBndSide[se][3] = 3;
     600              :                                         }
     601            0 :                                         if(i==p-1) // right
     602              :                                         {
     603            0 :                                                 vIsBndElem[se] = true;
     604            0 :                                                 vElemBndSide[se][1] = 1;
     605              :                                         }
     606            0 :                                         if(j==0) // bottom
     607              :                                         {
     608            0 :                                                 vIsBndElem[se] = true;
     609            0 :                                                 vElemBndSide[se][0] = 0;
     610              :                                         }
     611            0 :                                         if(j==p-1) // top
     612              :                                         {
     613            0 :                                                 vIsBndElem[se] = true;
     614            0 :                                                 vElemBndSide[se][2] = 2;
     615              :                                         }
     616            0 :                                         ++se;
     617              :                                 }
     618              :                         }
     619              : 
     620              :                         {
     621            0 :                                 FlexLagrangeLSFS<ReferenceQuadrilateral> set(p);
     622            0 :                                 for(size_t s = 0; s < se; ++s)
     623              :                                 {
     624            0 :                                         vIndex[s].resize(vvMultiIndex[s].size());
     625            0 :                                         for(size_t i = 0; i < vvMultiIndex[s].size(); ++i)
     626              :                                         {
     627            0 :                                                 vIndex[s][i] = set.index(vvMultiIndex[s][i]);
     628              :                                         }
     629              :                                 }
     630            0 :                         }
     631            0 :                         break;
     632            0 :                 default: UG_THROW("ReferenceElement not found.");
     633              :         }
     634              : 
     635            0 : }
     636              : 
     637              : template <>
     638            0 : void ComputeMultiIndicesOfSubElement<3>(std::vector<MathVector<3, int> >* vvMultiIndex,
     639              :                                         bool* vIsBndElem,
     640              :                                         std::vector<int>* vElemBndSide,
     641              :                                         std::vector<size_t>* vIndex,
     642              :                                         ReferenceObjectID roid,
     643              :                                         int p)
     644              : {
     645              : //      switch for roid
     646              :         size_t se = 0;
     647            0 :         switch(roid)
     648              :         {
     649              :                 case ROID_TETRAHEDRON:
     650            0 :                         for(int k = 0; k < p; ++k) {
     651            0 :                                 for(int j = 0; j < p -k; ++j) {
     652            0 :                                         for(int i = 0; i < p -k -j; ++i) {
     653            0 :                                                 vvMultiIndex[se].resize(4);
     654              :                                                 vvMultiIndex[se][0] = MathVector<3,int>(i  , j  , k);
     655            0 :                                                 vvMultiIndex[se][1] = MathVector<3,int>(i+1, j  , k);
     656            0 :                                                 vvMultiIndex[se][2] = MathVector<3,int>(i  , j+1, k);
     657            0 :                                                 vvMultiIndex[se][3] = MathVector<3,int>(i  , j  , k+1);
     658              : 
     659              :                                                 // reset bnd info
     660            0 :                                                 vIsBndElem[se] = false;
     661            0 :                                                 vElemBndSide[se].clear(); vElemBndSide[se].resize(4, -1);
     662              : 
     663            0 :                                                 if(i==0) // left
     664              :                                                 {
     665            0 :                                                         vIsBndElem[se] = true;
     666            0 :                                                         vElemBndSide[se][2] = 2;
     667              :                                                 }
     668            0 :                                                 if(j==0) // front
     669              :                                                 {
     670            0 :                                                         vIsBndElem[se] = true;
     671            0 :                                                         vElemBndSide[se][3] = 3;
     672              :                                                 }
     673            0 :                                                 if(k==0) // bottom
     674              :                                                 {
     675            0 :                                                         vIsBndElem[se] = true;
     676            0 :                                                         vElemBndSide[se][0] = 0;
     677              :                                                 }
     678            0 :                                                 if(i+j+k==p-1) // diag
     679              :                                                 {
     680            0 :                                                         vIsBndElem[se] = true;
     681            0 :                                                         vElemBndSide[se][1] = 1;
     682              :                                                 }
     683            0 :                                                 ++se;
     684              :                                         }
     685              :                                 }
     686              :                         }
     687              :                         //      build 4 tetrahedrons out of the remaining octogons
     688            0 :                         for(int k = 0; k < p; ++k) {
     689            0 :                                 for(int j = 1; j < p -k; ++j) {
     690            0 :                                         for(int i = 0; i < p -k -j; ++i) {
     691            0 :                                                 if(j >= 2){
     692            0 :                                                         vvMultiIndex[se].resize(4);
     693            0 :                                                         vvMultiIndex[se][0] = MathVector<3,int>(i+1, j-1, k);
     694            0 :                                                         vvMultiIndex[se][1] = MathVector<3,int>(i+1, j-1, k+1);
     695              :                                                         vvMultiIndex[se][2] = MathVector<3,int>(i  , j-1, k+1);
     696            0 :                                                         vvMultiIndex[se][3] = MathVector<3,int>(i+1, j-2, k+1);
     697              : 
     698              :                                                         // reset bnd info
     699            0 :                                                         vIsBndElem[se] = false;
     700            0 :                                                         vElemBndSide[se].clear(); vElemBndSide[se].resize(4, -1);
     701              : 
     702            0 :                                                         ++se;
     703              :                                                 }
     704              : 
     705            0 :                                                 vvMultiIndex[se].resize(4);
     706              :                                                 vvMultiIndex[se][0] = MathVector<3,int>(i  , j  , k);
     707            0 :                                                 vvMultiIndex[se][1] = MathVector<3,int>(i  , j  , k+1);
     708            0 :                                                 vvMultiIndex[se][2] = MathVector<3,int>(i  , j-1, k+1);
     709            0 :                                                 vvMultiIndex[se][3] = MathVector<3,int>(i+1, j-1, k+1);
     710              : 
     711              :                                                 // reset bnd info
     712            0 :                                                 vIsBndElem[se] = false;
     713            0 :                                                 vElemBndSide[se].clear(); vElemBndSide[se].resize(4, -1);
     714              : 
     715            0 :                                                 if(i==0) // left
     716              :                                                 {
     717            0 :                                                         vIsBndElem[se] = true;
     718            0 :                                                         vElemBndSide[se][0] = 2;
     719              :                                                 }
     720            0 :                                                 ++se;
     721              : 
     722            0 :                                                 vvMultiIndex[se].resize(4);
     723              :                                                 vvMultiIndex[se][0] = MathVector<3,int>(i  , j  , k);
     724            0 :                                                 vvMultiIndex[se][1] = MathVector<3,int>(i+1, j  , k);
     725              :                                                 vvMultiIndex[se][2] = MathVector<3,int>(i+1, j-1, k+1);
     726              :                                                 vvMultiIndex[se][3] = MathVector<3,int>(i+1, j-1, k);
     727              : 
     728              :                                                 // reset bnd info
     729            0 :                                                 vIsBndElem[se] = false;
     730            0 :                                                 vElemBndSide[se].clear(); vElemBndSide[se].resize(4, -1);
     731              : 
     732            0 :                                                 if(k==0) // bottom
     733              :                                                 {
     734            0 :                                                         vIsBndElem[se] = true;
     735            0 :                                                         vElemBndSide[se][2] = 0;
     736              :                                                 }
     737            0 :                                                 ++se;
     738              : 
     739            0 :                                                 vvMultiIndex[se].resize(4);
     740              :                                                 vvMultiIndex[se][0] = MathVector<3,int>(i  , j  , k);
     741              :                                                 vvMultiIndex[se][1] = MathVector<3,int>(i+1, j-1, k);
     742              :                                                 vvMultiIndex[se][2] = MathVector<3,int>(i+1, j-1, k+1);
     743              :                                                 vvMultiIndex[se][3] = MathVector<3,int>(i  , j-1, k+1);
     744              : 
     745              :                                                 // reset bnd info
     746            0 :                                                 vIsBndElem[se] = false;
     747            0 :                                                 vElemBndSide[se].clear(); vElemBndSide[se].resize(4, -1);
     748              : 
     749            0 :                                                 if(j==1) // front
     750              :                                                 {
     751            0 :                                                         vIsBndElem[se] = true;
     752            0 :                                                         vElemBndSide[se][1] = 3;
     753              :                                                 }
     754            0 :                                                 ++se;
     755              : 
     756            0 :                                                 vvMultiIndex[se].resize(4);
     757              :                                                 vvMultiIndex[se][0] = MathVector<3,int>(i  , j  , k);
     758              :                                                 vvMultiIndex[se][1] = MathVector<3,int>(i+1, j-1, k+1);
     759              :                                                 vvMultiIndex[se][2] = MathVector<3,int>(i+1, j  , k);
     760              :                                                 vvMultiIndex[se][3] = MathVector<3,int>(i  , j  , k+1);
     761              : 
     762              :                                                 // reset bnd info
     763            0 :                                                 vIsBndElem[se] = false;
     764            0 :                                                 vElemBndSide[se].clear(); vElemBndSide[se].resize(4, -1);
     765              : 
     766            0 :                                                 if(i+j+k==p-1) // diag
     767              :                                                 {
     768            0 :                                                         vIsBndElem[se] = true;
     769            0 :                                                         vElemBndSide[se][1] = 1;
     770              :                                                 }
     771            0 :                                                 ++se;
     772              :                                         }
     773              :                                 }
     774              :                         }
     775              : 
     776              :                         {
     777            0 :                                 FlexLagrangeLSFS<ReferenceTetrahedron> set(p);
     778            0 :                                 for(size_t s = 0; s < se; ++s)
     779              :                                 {
     780            0 :                                         vIndex[s].resize(vvMultiIndex[s].size());
     781            0 :                                         for(size_t i = 0; i < vvMultiIndex[s].size(); ++i)
     782              :                                         {
     783            0 :                                                 vIndex[s][i] = set.index(vvMultiIndex[s][i]);
     784              :                                         }
     785              :                                 }
     786            0 :                         }
     787            0 :                         break;
     788              : 
     789              :                 case ROID_PRISM:
     790            0 :                         for(int k = 0; k < p; ++k) {
     791            0 :                                 for(int j = 0; j < p; ++j) {
     792            0 :                                         for(int i = 0; i < p - j; ++i) {
     793            0 :                                                 vvMultiIndex[se].resize(6);
     794              :                                                 vvMultiIndex[se][0] = MathVector<3,int>(i  , j  , k);
     795            0 :                                                 vvMultiIndex[se][1] = MathVector<3,int>(i+1, j  , k);
     796            0 :                                                 vvMultiIndex[se][2] = MathVector<3,int>(i  , j+1, k);
     797            0 :                                                 vvMultiIndex[se][3] = MathVector<3,int>(i  , j  , k+1);
     798              :                                                 vvMultiIndex[se][4] = MathVector<3,int>(i+1, j  , k+1);
     799              :                                                 vvMultiIndex[se][5] = MathVector<3,int>(i  , j+1, k+1);
     800              : 
     801              :                                                 // reset bnd info
     802            0 :                                                 vIsBndElem[se] = false;
     803            0 :                                                 vElemBndSide[se].clear(); vElemBndSide[se].resize(5, -1);
     804              : 
     805            0 :                                                 if(i==0) // left
     806              :                                                 {
     807            0 :                                                         vIsBndElem[se] = true;
     808            0 :                                                         vElemBndSide[se][3] = 3;
     809              :                                                 }
     810            0 :                                                 if(j==0) // front
     811              :                                                 {
     812            0 :                                                         vIsBndElem[se] = true;
     813            0 :                                                         vElemBndSide[se][1] = 1;
     814              :                                                 }
     815            0 :                                                 if(i+j==p-1) // diag
     816              :                                                 {
     817            0 :                                                         vIsBndElem[se] = true;
     818            0 :                                                         vElemBndSide[se][2] = 2;
     819              :                                                 }
     820            0 :                                                 if(k==0) // bottom
     821              :                                                 {
     822            0 :                                                         vIsBndElem[se] = true;
     823            0 :                                                         vElemBndSide[se][0] = 0;
     824              :                                                 }
     825            0 :                                                 if(k==p-1) // top
     826              :                                                 {
     827            0 :                                                         vIsBndElem[se] = true;
     828            0 :                                                         vElemBndSide[se][4] = 4;
     829              :                                                 }
     830            0 :                                                 ++se;
     831              :                                         }
     832              :                                 }
     833              :                         }
     834            0 :                         for(int k = 0; k < p; ++k) {
     835            0 :                                 for(int j = 1; j <= p; ++j) {
     836            0 :                                         for(int i = 1; i <= p - j; ++i) {
     837            0 :                                                 vvMultiIndex[se].resize(6);
     838              :                                                 vvMultiIndex[se][0] = MathVector<3,int>(i  , j  ,k);
     839            0 :                                                 vvMultiIndex[se][1] = MathVector<3,int>(i-1, j  ,k);
     840            0 :                                                 vvMultiIndex[se][2] = MathVector<3,int>(i  , j-1,k);
     841            0 :                                                 vvMultiIndex[se][3] = MathVector<3,int>(i  , j  ,k+1);
     842              :                                                 vvMultiIndex[se][4] = MathVector<3,int>(i-1, j  ,k+1);
     843              :                                                 vvMultiIndex[se][5] = MathVector<3,int>(i  , j-1,k+1);
     844              : 
     845              :                                                 // reset bnd info
     846            0 :                                                 vIsBndElem[se] = false;
     847            0 :                                                 vElemBndSide[se].clear(); vElemBndSide[se].resize(5, -1);
     848              : 
     849            0 :                                                 if(k==0) // bottom
     850              :                                                 {
     851            0 :                                                         vIsBndElem[se] = true;
     852            0 :                                                         vElemBndSide[se][0] = 0;
     853              :                                                 }
     854            0 :                                                 if(k==p-1) // top
     855              :                                                 {
     856            0 :                                                         vIsBndElem[se] = true;
     857            0 :                                                         vElemBndSide[se][4] = 4;
     858              :                                                 }
     859            0 :                                                 ++se;
     860              :                                         }
     861              :                                 }
     862              :                         }
     863              : 
     864              :                         {
     865            0 :                                 FlexLagrangeLSFS<ReferencePrism> set(p);
     866            0 :                                 for(size_t s = 0; s < se; ++s)
     867              :                                 {
     868            0 :                                         vIndex[s].resize(vvMultiIndex[s].size());
     869            0 :                                         for(size_t i = 0; i < vvMultiIndex[s].size(); ++i)
     870              :                                         {
     871            0 :                                                 vIndex[s][i] = set.index(vvMultiIndex[s][i]);
     872              :                                         }
     873              :                                 }
     874            0 :                         }
     875              : 
     876            0 :                         break;
     877              :                 case ROID_HEXAHEDRON:
     878            0 :                         for(int k = 0; k < p; ++k) {
     879            0 :                                 for(int j = 0; j < p; ++j) {
     880            0 :                                         for(int i = 0; i < p; ++i) {
     881            0 :                                                 vvMultiIndex[se].resize(8);
     882              :                                                 vvMultiIndex[se][0] = MathVector<3,int>(i  , j  , k);
     883            0 :                                                 vvMultiIndex[se][1] = MathVector<3,int>(i+1, j  , k);
     884            0 :                                                 vvMultiIndex[se][2] = MathVector<3,int>(i+1, j+1, k);
     885              :                                                 vvMultiIndex[se][3] = MathVector<3,int>(i  , j+1, k);
     886            0 :                                                 vvMultiIndex[se][4] = MathVector<3,int>(i  , j  , k+1);
     887              :                                                 vvMultiIndex[se][5] = MathVector<3,int>(i+1, j  , k+1);
     888              :                                                 vvMultiIndex[se][6] = MathVector<3,int>(i+1, j+1, k+1);
     889              :                                                 vvMultiIndex[se][7] = MathVector<3,int>(i  , j+1, k+1);
     890              : 
     891              :                                                 // reset bnd info
     892            0 :                                                 vIsBndElem[se] = false;
     893            0 :                                                 vElemBndSide[se].clear(); vElemBndSide[se].resize(6, -1);
     894              : 
     895            0 :                                                 if(i==0) // left
     896              :                                                 {
     897            0 :                                                         vIsBndElem[se] = true;
     898            0 :                                                         vElemBndSide[se][4] = 4;
     899              :                                                 }
     900            0 :                                                 if(i==p-1) //right
     901              :                                                 {
     902            0 :                                                         vIsBndElem[se] = true;
     903            0 :                                                         vElemBndSide[se][2] = 2;
     904              :                                                 }
     905            0 :                                                 if(j==0) // front
     906              :                                                 {
     907            0 :                                                         vIsBndElem[se] = true;
     908            0 :                                                         vElemBndSide[se][1] = 1;
     909              :                                                 }
     910            0 :                                                 if(j==p-1) // back
     911              :                                                 {
     912            0 :                                                         vIsBndElem[se] = true;
     913            0 :                                                         vElemBndSide[se][3] = 3;
     914              :                                                 }
     915            0 :                                                 if(k==0) // bottom
     916              :                                                 {
     917            0 :                                                         vIsBndElem[se] = true;
     918            0 :                                                         vElemBndSide[se][0] = 0;
     919              :                                                 }
     920            0 :                                                  if(k==p-1) // top
     921              :                                                 {
     922            0 :                                                         vIsBndElem[se] = true;
     923            0 :                                                         vElemBndSide[se][5] = 5;
     924              :                                                 }
     925            0 :                                                 ++se;
     926              :                                         }
     927              :                                 }
     928              :                         }
     929              : 
     930              :                         {
     931            0 :                                 FlexLagrangeLSFS<ReferenceHexahedron> set(p);
     932            0 :                                 for(size_t s = 0; s < se; ++s)
     933              :                                 {
     934            0 :                                         vIndex[s].resize(vvMultiIndex[s].size());
     935            0 :                                         for(size_t i = 0; i < vvMultiIndex[s].size(); ++i)
     936              :                                         {
     937            0 :                                                 vIndex[s][i] = set.index(vvMultiIndex[s][i]);
     938              :                                         }
     939              :                                 }
     940            0 :                         }
     941              : 
     942            0 :                         break;
     943            0 :                 default: UG_THROW("ReferenceElement not found.");
     944              :         }
     945              : 
     946            0 : }
     947              : 
     948              : 
     949              : ////////////////////////////////////////////////////////////////////////////////
     950              : ////////////////////////////////////////////////////////////////////////////////
     951              : // FV Geometry for Reference Element Type (all order, FVHO)
     952              : ////////////////////////////////////////////////////////////////////////////////
     953              : ////////////////////////////////////////////////////////////////////////////////
     954              : 
     955              : template <int TOrder, typename TElem, int TWorldDim, int TQuadOrder>
     956            0 : FVGeometry<TOrder, TElem, TWorldDim, TQuadOrder>::
     957              : FVGeometry()
     958            0 :         : m_pElem(NULL), m_rRefElem(Provider<ref_elem_type>::get()),
     959            0 :           m_rTrialSpace(Provider<local_shape_fct_set_type>::get()),
     960            0 :           m_rSCVFQuadRule(Provider<scvf_quad_rule_type>::get()),
     961            0 :           m_rSCVQuadRule(Provider<scv_quad_rule_type>::get())
     962              : {
     963            0 :         update_local_data();
     964            0 : }
     965              : 
     966              : template <int TOrder, typename TElem, int TWorldDim, int TQuadOrder>
     967            0 : void FVGeometry<TOrder, TElem, TWorldDim, TQuadOrder>::
     968              : update_local(ReferenceObjectID roid, const LFEID& lfeID,
     969              :                   size_t quadOrder)
     970              : {
     971            0 :         if(roid != geometry_traits<TElem>::REFERENCE_OBJECT_ID)
     972              :         {
     973            0 :                 UG_THROW("FVGeometry::update: Geometry only for "
     974              :                                 <<geometry_traits<TElem>::REFERENCE_OBJECT_ID<<", but "
     975              :                                 <<roid<<" requested.");
     976              :         }
     977            0 :         if(lfeID.type() != LFEID::LAGRANGE)
     978              :         {
     979            0 :                 UG_THROW("FVGeometry::update: Geometry only for shape type"
     980              :                                 <<"Lagrange"<<", but "<<lfeID.type()<<" requested.");
     981              :         }
     982            0 :         if(lfeID.order() != TOrder)
     983              :         {
     984            0 :                 UG_THROW("FVGeometry::update: Geometry only for shape order"
     985              :                                 <<TOrder<<", but "<<lfeID.order()<<" requested.");
     986              :         }
     987            0 :         if(quadOrder > TQuadOrder)
     988              :         {
     989            0 :                 UG_THROW("FVGeometry::update: Geometry only for scvf integration order "
     990              :                                 << TQuadOrder<<", but order "<<quadOrder<<" requested.");
     991              :         }
     992            0 : }
     993              : 
     994              : 
     995              : template <int TOrder, typename TElem, int TWorldDim, int TQuadOrder>
     996            0 : void FVGeometry<TOrder, TElem, TWorldDim, TQuadOrder>::
     997              : update_local_data()
     998              : {
     999              : //      get reference object id
    1000              :         ReferenceObjectID roid = ref_elem_type::REFERENCE_OBJECT_ID;
    1001              : 
    1002              : //      determine corners of sub elements
    1003              :         bool vIsBndElem[numSubElem];
    1004            0 :         std::vector<int> vElemBndSide[numSubElem];
    1005            0 :         std::vector<size_t> vIndex[numSubElem];
    1006            0 :         std::vector<MathVector<dim,int> > vMultiIndex[numSubElem];
    1007              : 
    1008            0 :         ComputeMultiIndicesOfSubElement<dim>(vMultiIndex, vIsBndElem,
    1009              :                                                                                  vElemBndSide, vIndex, roid, p);
    1010              : 
    1011              : //      directions of counting
    1012            0 :         MathVector<dim> direction[dim];
    1013            0 :         for(int i = 0; i < dim; ++i){direction[i] = 0.0; direction[i][i] = 1.0;}
    1014              : 
    1015            0 :         for(size_t se = 0; se < numSubElem; ++se)
    1016              :         {
    1017            0 :                 for(int co = 0; co < ref_elem_type::numCorners; ++co)
    1018              :                 {
    1019              :                 //      compute corners of sub elem in local coordinates
    1020              :                         MathVector<dim> pos; pos = 0.0;
    1021            0 :                         for(int i = 0; i < dim; ++i)
    1022              :                         {
    1023            0 :                                 const number frac = vMultiIndex[se][co][i] / ((number)p);
    1024              :                                 VecScaleAppend(pos, frac, direction[i]);
    1025              :                         }
    1026              :                         m_vSubElem[se].vvLocMid[0][co] = pos;
    1027              : 
    1028              :                 //      get multi index for corner
    1029            0 :                         m_vSubElem[se].vDoFID[co] = vIndex[se][co];
    1030              :                 }
    1031              : 
    1032              :         //      remember if boundary element
    1033            0 :                 m_vSubElem[se].isBndElem = vIsBndElem[se];
    1034              : 
    1035              :         //      remember boundary sides
    1036            0 :                 m_vSubElem[se].vElemBndSide = vElemBndSide[se];
    1037              :         }
    1038              : 
    1039              : //      compute mid points for all sub elements
    1040            0 :         for(size_t se = 0; se < numSubElem; ++se)
    1041              :                 ComputeMidPoints<dim, ref_elem_type, maxMid>
    1042            0 :                                 (m_rRefElem, m_vSubElem[se].vvLocMid[0], m_vSubElem[se].vvLocMid);
    1043              : 
    1044              : //      set up local informations for SubControlVolumeFaces (scvf)
    1045              : //      each scvf is associated to one edge of the sub-element
    1046            0 :         for(size_t i = 0; i < num_scvf(); ++i)
    1047              :         {
    1048              :         //      get corresponding subelement
    1049            0 :                 const size_t se = i / numSCVFPerSubElem;
    1050            0 :                 const size_t locSCVF = i % numSCVFPerSubElem;
    1051              : 
    1052              :         //      this scvf separates the given nodes
    1053            0 :                 const size_t locFrom =  m_rRefElem.id(1, locSCVF, 0, 0);
    1054            0 :                 const size_t locTo =  m_rRefElem.id(1, locSCVF, 0, 1);
    1055              : 
    1056            0 :                 m_vSCVF[i].From = m_vSubElem[se].vDoFID[locFrom];
    1057            0 :                 m_vSCVF[i].To = m_vSubElem[se].vDoFID[locTo];
    1058              : 
    1059              :         //      compute mid ids of the scvf
    1060            0 :                 ComputeSCVFMidID(m_rRefElem, m_vSCVF[i].vMidID, locSCVF);
    1061              : 
    1062              :         //      copy local corners of scvf
    1063              :                 CopyCornerByMidID<dim, maxMid>
    1064            0 :                         (m_vSCVF[i].vLocPos, m_vSCVF[i].vMidID, m_vSubElem[se].vvLocMid, SCVF::numCo);
    1065              : 
    1066              :         //      compute integration points
    1067            0 :                 m_vSCVF[i].vWeight = m_rSCVFQuadRule.weights();
    1068            0 :                 ReferenceMapping<scvf_type, dim> map(m_vSCVF[i].vLocPos);
    1069            0 :                 for(size_t ip = 0; ip < m_rSCVFQuadRule.size(); ++ip)
    1070            0 :                         map.local_to_global(m_vSCVF[i].vLocalIP[ip], m_rSCVFQuadRule.point(ip));
    1071              :         }
    1072              : 
    1073              : 
    1074              : //      set up local informations for SubControlVolumes (scv)
    1075              : //      each scv is associated to one corner of the sub-element
    1076            0 :         for(size_t i = 0; i < num_scv(); ++i)
    1077              :         {
    1078              :         //      get corresponding subelement
    1079            0 :                 const size_t se = i / numSCVPerSubElem;
    1080            0 :                 const size_t locSCV = i % numSCVPerSubElem;
    1081              : 
    1082              :         //      store associated node
    1083            0 :                 m_vSCV[i].nodeId = m_vSubElem[se].vDoFID[locSCV];;
    1084              : 
    1085              :         //      compute mid ids scv
    1086            0 :                 ComputeSCVMidID(m_rRefElem, m_vSCV[i].vMidID, locSCV);
    1087              : 
    1088              :         //      copy local corners of scv
    1089              :                 CopyCornerByMidID<dim, maxMid>
    1090            0 :                         (m_vSCV[i].vLocPos, m_vSCV[i].vMidID, m_vSubElem[se].vvLocMid, m_vSCV[i].num_corners());
    1091              : 
    1092              :         //      compute integration points
    1093            0 :                 m_vSCV[i].vWeight = m_rSCVQuadRule.weights();
    1094            0 :                 ReferenceMapping<scv_type, dim> map(m_vSCV[i].vLocPos);
    1095            0 :                 for(size_t ip = 0; ip < m_rSCVQuadRule.size(); ++ip)
    1096            0 :                         map.local_to_global(m_vSCV[i].vLocalIP[ip], m_rSCVQuadRule.point(ip));
    1097              :         }
    1098              : 
    1099              :         /////////////////////////
    1100              :         // Shapes and Derivatives
    1101              :         /////////////////////////
    1102              : 
    1103            0 :         for(size_t i = 0; i < num_scvf(); ++i)
    1104            0 :                 for(size_t ip = 0; ip < m_vSCVF[i].num_ip(); ++ip)
    1105              :                 {
    1106            0 :                         m_rTrialSpace.shapes(&(m_vSCVF[i].vvShape[ip][0]), m_vSCVF[i].local_ip(ip));
    1107            0 :                         m_rTrialSpace.grads(&(m_vSCVF[i].vvLocalGrad[ip][0]), m_vSCVF[i].local_ip(ip));
    1108              :                 }
    1109              : 
    1110            0 :         for(size_t i = 0; i < num_scv(); ++i)
    1111            0 :                 for(size_t ip = 0; ip < m_vSCV[i].num_ip(); ++ip)
    1112              :                 {
    1113            0 :                         m_rTrialSpace.shapes(&(m_vSCV[i].vvShape[ip][0]), m_vSCV[i].local_ip(ip));
    1114            0 :                         m_rTrialSpace.grads(&(m_vSCV[i].vvLocalGrad[ip][0]), m_vSCV[i].local_ip(ip));
    1115              :                 }
    1116              : 
    1117              : //      copy ip positions in a list for Sub Control Volumes Faces (SCVF)
    1118              :         size_t allIP = 0;
    1119            0 :         for(size_t i = 0; i < num_scvf(); ++i)
    1120            0 :                 for(size_t ip = 0; ip < m_vSCVF[i].num_ip(); ++ip)
    1121            0 :                         m_vLocSCVF_IP[allIP++] = scvf(i).local_ip(ip);
    1122              : 
    1123              : //      copy ip positions in a list for Sub Control Volumes (SCV)
    1124              :         allIP = 0;
    1125            0 :         for(size_t i = 0; i < num_scv(); ++i)
    1126            0 :                 for(size_t ip = 0; ip < m_vSCV[i].num_ip(); ++ip)
    1127            0 :                         m_vLocSCV_IP[allIP++] = scv(i).local_ip(ip);
    1128            0 : }
    1129              : 
    1130              : 
    1131              : /// update data for given element
    1132              : template <int TOrder, typename TElem, int TWorldDim, int TQuadOrder>
    1133            0 : void FVGeometry<TOrder, TElem, TWorldDim, TQuadOrder>::
    1134              : update(GridObject* elem, const MathVector<worldDim>* vCornerCoords, const ISubsetHandler* ish)
    1135              : {
    1136              :         UG_ASSERT(dynamic_cast<TElem*>(elem) != NULL, "Wrong element type.");
    1137              :         TElem* pElem = static_cast<TElem*>(elem);
    1138              : 
    1139              : //      If already update for this element, do nothing
    1140            0 :         if(m_pElem == pElem) return; else m_pElem = pElem;
    1141              : 
    1142              : //      update reference mapping
    1143            0 :         m_rMapping.update(vCornerCoords);
    1144              : 
    1145              : //      compute global informations for scvf
    1146            0 :         for(size_t i = 0; i < num_scvf(); ++i)
    1147              :         {
    1148              :         //      map local corners of scvf to global
    1149            0 :                 for(size_t co = 0; co < m_vSCVF[i].num_corners(); ++co)
    1150            0 :                         m_rMapping.local_to_global(m_vSCVF[i].vGloPos[co], m_vSCVF[i].vLocPos[co]);
    1151              : 
    1152              :         //      map local ips of scvf to global
    1153            0 :                 for(size_t ip = 0; ip < m_vSCVF[i].num_ip(); ++ip)
    1154            0 :                         m_rMapping.local_to_global(m_vSCVF[i].vGlobalIP[ip], m_vSCVF[i].local_ip(ip));
    1155              : 
    1156              :         //      normal on scvf
    1157            0 :                 traits::NormalOnSCVF(m_vSCVF[i].Normal, m_vSCVF[i].vGloPos, vCornerCoords);
    1158            0 :                 VecNormalize(m_vSCVF[i].Normal, m_vSCVF[i].Normal);
    1159              : 
    1160            0 :                 ReferenceMapping<scvf_type, worldDim> map(&m_vSCVF[i].vGloPos[0]);
    1161            0 :                 for(size_t ip = 0; ip < m_rSCVFQuadRule.size(); ++ip)
    1162            0 :                         m_vSCVF[i].vDetJMap[ip] = map.sqrt_gram_det(m_rSCVFQuadRule.point(ip));
    1163              :         }
    1164              : 
    1165              : //      compute size of scv
    1166            0 :         for(size_t i = 0; i < num_scv(); ++i)
    1167              :         {
    1168              :         //      map local corners of scvf to global
    1169            0 :                 for(size_t co = 0; co < m_vSCV[i].num_corners(); ++co)
    1170            0 :                         m_rMapping.local_to_global(m_vSCV[i].vGloPos[co], m_vSCV[i].vLocPos[co]);
    1171              : 
    1172              :         //      map local ips of scvf to global
    1173            0 :                 for(size_t ip = 0; ip < m_vSCV[i].num_ip(); ++ip)
    1174            0 :                         m_rMapping.local_to_global(m_vSCV[i].vGlobalIP[ip], m_vSCV[i].local_ip(ip));
    1175              :         }
    1176              : 
    1177              : //      if mapping is linear, compute jacobian only once and copy
    1178              :         if(ReferenceMapping<ref_elem_type, worldDim>::isLinear)
    1179              :         {
    1180              :                 MathMatrix<worldDim,dim> JtInv;
    1181            0 :                 m_rMapping.jacobian_transposed_inverse(JtInv, m_vSCVF[0].local_ip(0));
    1182            0 :                 const number detJ = m_rMapping.sqrt_gram_det(m_vSCVF[0].local_ip(0));
    1183            0 :                 for(size_t i = 0; i < num_scvf(); ++i)
    1184            0 :                         for(size_t ip = 0; ip < scvf(i).num_ip(); ++ip)
    1185              :                         {
    1186              :                                 m_vSCVF[i].vJtInv[ip] = JtInv;
    1187            0 :                                 m_vSCVF[i].vDetJ[ip] = detJ;
    1188              :                         }
    1189              : 
    1190            0 :                 for(size_t i = 0; i < num_scv(); ++i)
    1191            0 :                         for(size_t ip = 0; ip < scv(i).num_ip(); ++ip)
    1192              :                         {
    1193              :                                 m_vSCV[i].vJtInv[ip] = JtInv;
    1194            0 :                                 m_vSCV[i].vDetJ[ip] = detJ;
    1195              :                         }
    1196              :         }
    1197              : //      else compute jacobian for each integration point
    1198              :         else
    1199              :         {
    1200            0 :                 for(size_t i = 0; i < num_scvf(); ++i)
    1201            0 :                         for(size_t ip = 0; ip < m_vSCVF[i].num_ip(); ++ip)
    1202              :                         {
    1203            0 :                                 m_rMapping.jacobian_transposed_inverse(m_vSCVF[i].vJtInv[ip], m_vSCVF[i].local_ip(ip));
    1204            0 :                                 m_vSCVF[i].vDetJ[ip] = m_rMapping.sqrt_gram_det(m_vSCVF[i].local_ip(ip));
    1205              :                         }
    1206              : 
    1207            0 :                 for(size_t i = 0; i < num_scv(); ++i)
    1208            0 :                         for(size_t ip = 0; ip < m_vSCV[i].num_ip(); ++ip)
    1209              :                         {
    1210            0 :                                 m_rMapping.jacobian_transposed_inverse(m_vSCV[i].vJtInv[ip], m_vSCV[i].local_ip(ip));
    1211            0 :                                 m_vSCV[i].vDetJ[ip] = m_rMapping.sqrt_gram_det(m_vSCV[i].local_ip(ip));
    1212              :                         }
    1213              :         }
    1214              : 
    1215            0 :         for(size_t i = 0; i < num_scv(); ++i)
    1216              :         {
    1217            0 :                 ReferenceMapping<scv_type, worldDim> map(&m_vSCV[i].vGloPos[0]);
    1218            0 :                 for(size_t ip = 0; ip < m_rSCVQuadRule.size(); ++ip)
    1219            0 :                         m_vSCV[i].vDetJMap[ip] = map.sqrt_gram_det(m_rSCVQuadRule.point(ip));
    1220              :         }
    1221              : 
    1222              : //      compute global gradients
    1223            0 :         for(size_t i = 0; i < num_scvf(); ++i)
    1224            0 :                 for(size_t ip = 0; ip < scvf(i).num_ip(); ++ip)
    1225            0 :                         for(size_t sh = 0 ; sh < nsh; ++sh)
    1226            0 :                                 MatVecMult(m_vSCVF[i].vvGlobalGrad[ip][sh], m_vSCVF[i].vJtInv[ip], m_vSCVF[i].vvLocalGrad[ip][sh]);
    1227              : 
    1228            0 :         for(size_t i = 0; i < num_scv(); ++i)
    1229            0 :                 for(size_t ip = 0; ip < scv(i).num_ip(); ++ip)
    1230            0 :                         for(size_t sh = 0 ; sh < nsh; ++sh)
    1231            0 :                                 MatVecMult(m_vSCV[i].vvGlobalGrad[ip][sh], m_vSCV[i].vJtInv[ip], m_vSCV[i].vvLocalGrad[ip][sh]);
    1232              : 
    1233              : //      Copy ip pos in list for SCVF
    1234              :         size_t allIP = 0;
    1235            0 :         for(size_t i = 0; i < num_scvf(); ++i)
    1236            0 :                 for(size_t ip = 0; ip < scvf(i).num_ip(); ++ip)
    1237            0 :                         m_vGlobSCVF_IP[allIP++] = scvf(i).global_ip(ip);
    1238              : 
    1239              :         allIP = 0;
    1240            0 :         for(size_t i = 0; i < num_scv(); ++i)
    1241            0 :                 for(size_t ip = 0; ip < scv(i).num_ip(); ++ip)
    1242            0 :                         m_vGlobSCV_IP[allIP++] = scv(i).global_ip(ip);
    1243              : 
    1244              : //      if no boundary subsets required, return
    1245            0 :         if(num_boundary_subsets() == 0 || ish == NULL) return;
    1246            0 :         else update_boundary_faces(pElem, vCornerCoords, ish);
    1247              : }
    1248              : 
    1249              : template <int TOrder, typename TElem, int TWorldDim, int TQuadOrder>
    1250            0 : void FVGeometry<TOrder, TElem, TWorldDim, TQuadOrder>::
    1251              : update_boundary_faces(GridObject* elem, const MathVector<worldDim>* vCornerCoords, const ISubsetHandler* ish)
    1252              : {
    1253              :         UG_ASSERT(dynamic_cast<TElem*>(elem) != NULL, "Wrong element type.");
    1254              :         TElem* pElem = static_cast<TElem*>(elem);
    1255              : 
    1256              : //      get grid
    1257            0 :         Grid& grid = *(ish->grid());
    1258              : 
    1259              : //      vector of subset indices of side
    1260              :         std::vector<int> vSubsetIndex;
    1261              : 
    1262              : //      get subset indices for sides (i.e. edge in 2d, faces in 3d)
    1263              :         if(dim == 1) {
    1264              :                 std::vector<Vertex*> vVertex;
    1265            0 :                 CollectVertices(vVertex, grid, pElem);
    1266            0 :                 vSubsetIndex.resize(vVertex.size());
    1267            0 :                 for(size_t i = 0; i < vVertex.size(); ++i)
    1268            0 :                         vSubsetIndex[i] = ish->get_subset_index(vVertex[i]);
    1269            0 :         }
    1270              :         if(dim == 2) {
    1271              :                 std::vector<Edge*> vEdges;
    1272            0 :                 CollectEdgesSorted(vEdges, grid, pElem);
    1273            0 :                 vSubsetIndex.resize(vEdges.size());
    1274            0 :                 for(size_t i = 0; i < vEdges.size(); ++i)
    1275            0 :                         vSubsetIndex[i] = ish->get_subset_index(vEdges[i]);
    1276            0 :         }
    1277              :         if(dim == 3) {
    1278              :                 std::vector<Face*> vFaces;
    1279            0 :                 CollectFacesSorted(vFaces, grid, pElem);
    1280            0 :                 vSubsetIndex.resize(vFaces.size());
    1281            0 :                 for(size_t i = 0; i < vFaces.size(); ++i)
    1282            0 :                         vSubsetIndex[i] = ish->get_subset_index(vFaces[i]);
    1283            0 :         }
    1284              : 
    1285              : //      update reference mapping
    1286            0 :         m_rMapping.update(vCornerCoords);
    1287              : 
    1288              : //      loop requested subset
    1289              :         typename std::map<int, std::vector<BF> >::iterator it;
    1290            0 :         for (it=m_mapVectorBF.begin() ; it != m_mapVectorBF.end(); ++it)
    1291              :         {
    1292              :         //      get subset index
    1293            0 :                 const int bndIndex = (*it).first;
    1294              : 
    1295              :         //      get vector of BF for element
    1296            0 :                 std::vector<BF>& vBF = (*it).second;
    1297              : 
    1298              :         //      clear vector
    1299              :                 vBF.clear();
    1300              : 
    1301              :         //      current number of bf
    1302              :                 size_t curr_bf = 0;
    1303              : 
    1304              :         //      loop subelements
    1305            0 :                 for(size_t se = 0; se < numSubElem; ++se)
    1306              :                 {
    1307              :                 //      skip inner sub elements
    1308            0 :                         if(!m_vSubElem[se].isBndElem) continue;
    1309              : 
    1310              :                 //      loop sides of element
    1311            0 :                         for(size_t side = 0; side < m_vSubElem[se].vElemBndSide.size(); ++side)
    1312              :                         {
    1313              :                         //      get whole element bnd side
    1314            0 :                                 const int elemBndSide = m_vSubElem[se].vElemBndSide[side];
    1315              : 
    1316              :                         //      skip non boundary sides
    1317            0 :                                 if(elemBndSide == -1 || vSubsetIndex[elemBndSide] != bndIndex) continue;
    1318              : 
    1319              :                         //      number of corners of side
    1320            0 :                                 const int coOfSide = m_rRefElem.num(dim-1, elemBndSide, 0);
    1321              : 
    1322              :                         //      resize vector
    1323            0 :                                 vBF.resize(curr_bf + coOfSide);
    1324              : 
    1325              :                         //      loop corners
    1326            0 :                                 for(int co = 0; co < coOfSide; ++co)
    1327              :                                 {
    1328              :                                 //      get current bf
    1329              :                                         BF& bf = vBF[curr_bf];
    1330              : 
    1331              :                                 //      set node id == scv this bf belongs to
    1332            0 :                                         const int refNodeId = m_rRefElem.id(dim-1, elemBndSide, 0, co);
    1333            0 :                                         bf.nodeId = m_vSubElem[se].vDoFID[refNodeId];
    1334              : 
    1335              :                                 //      Compute MidID for BF
    1336            0 :                                         ComputeBFMidID(m_rRefElem, elemBndSide, bf.vMidID, co);
    1337              : 
    1338              :                                 //      copy corners of bf
    1339              :                                         CopyCornerByMidID<dim, maxMid>
    1340            0 :                                                 (bf.vLocPos, bf.vMidID, m_vSubElem[se].vvLocMid, BF::numCo);
    1341              : //                                      CopyCornerByMidID<worldDim, maxMid>
    1342              : //                                              (bf.vGloPos, bf.vMidID, m_vSubElem[se].vvGloMid, BF::numCo);
    1343              :                                 //      compute global corners of bf
    1344            0 :                                         for(size_t i = 0; i < bf.num_corners(); ++i)
    1345            0 :                                                 m_rMapping.local_to_global(bf.vGloPos[i], bf.vLocPos[i]);
    1346              : 
    1347              :                                 //      normal on scvf
    1348            0 :                                         traits::NormalOnSCVF(bf.Normal, bf.vGloPos, m_vSubElem[se].vvGloMid[0]);
    1349              : 
    1350              :                                 //      compute local integration points
    1351            0 :                                         bf.vWeight = m_rSCVFQuadRule.weights();
    1352            0 :                                         ReferenceMapping<scvf_type, dim> map(bf.vLocPos);
    1353            0 :                                         for(size_t ip = 0; ip < m_rSCVFQuadRule.size(); ++ip)
    1354            0 :                                                 map.local_to_global(bf.vLocalIP[ip], m_rSCVFQuadRule.point(ip));
    1355              : 
    1356              :                                 //      compute global integration points
    1357            0 :                                         for(size_t ip = 0; ip < bf.num_ip(); ++ip)
    1358            0 :                                                 m_rMapping.local_to_global(bf.vGlobalIP[ip], bf.vLocalIP[ip]);
    1359              : 
    1360              :                                 //      compute volume
    1361            0 :                                         bf.Vol = VecTwoNorm(bf.Normal);
    1362              : 
    1363              :                                 //      compute shapes and gradients
    1364            0 :                                         for(size_t ip = 0; ip < bf.num_ip(); ++ip)
    1365              :                                         {
    1366            0 :                                                 m_rTrialSpace.shapes(&(bf.vvShape[ip][0]), bf.local_ip(ip));
    1367            0 :                                                 m_rTrialSpace.grads(&(bf.vvLocalGrad[ip][0]), bf.local_ip(ip));
    1368              : 
    1369            0 :                                                 m_rMapping.jacobian_transposed_inverse(bf.vJtInv[ip], bf.local_ip(ip));
    1370            0 :                                                 bf.vDetJ[ip] = m_rMapping.sqrt_gram_det(bf.local_ip(ip));
    1371              :                                         }
    1372              : 
    1373              :                                 //      compute global gradient
    1374            0 :                                         for(size_t ip = 0; ip < bf.num_ip(); ++ip)
    1375            0 :                                                 for(size_t sh = 0 ; sh < bf.num_sh(); ++sh)
    1376              :                                                         MatVecMult(bf.vvGlobalGrad[ip][sh],
    1377            0 :                                                                    bf.vJtInv[ip], bf.vvLocalGrad[ip][sh]);
    1378              : 
    1379              :                                 //      increase curr_bf
    1380            0 :                                         ++curr_bf;
    1381              :                                 }
    1382              :                         }
    1383              :                 }
    1384              :         }
    1385            0 : }
    1386              : 
    1387              : 
    1388              : ////////////////////////////////////////////////////////////////////////////////
    1389              : ////////////////////////////////////////////////////////////////////////////////
    1390              : // FV Geometry (all order, FVHO)   DIM FV
    1391              : ////////////////////////////////////////////////////////////////////////////////
    1392              : ////////////////////////////////////////////////////////////////////////////////
    1393              : 
    1394              : template <int TWorldDim, int TDim>
    1395            0 : DimFVGeometry<TWorldDim, TDim>::
    1396            0 : DimFVGeometry() : m_pElem(NULL) {}
    1397              : 
    1398              : 
    1399              : 
    1400              : template <int TWorldDim, int TDim>
    1401            0 : void DimFVGeometry<TWorldDim, TDim>::
    1402              : update_local(ReferenceObjectID roid, const LFEID& lfeID, size_t orderQuad)
    1403              : {
    1404              : //      save setting we prepare the local data for
    1405            0 :         m_roid = roid;
    1406            0 :         m_lfeID = lfeID;
    1407            0 :         m_orderShape = m_lfeID.order();
    1408            0 :         m_quadOrderSCVF = orderQuad;
    1409            0 :         m_quadOrderSCV = orderQuad;
    1410              : 
    1411              : //      resize sub elements
    1412            0 :         m_numSubElem = (size_t) std::pow((double) m_orderShape, dim);
    1413            0 :         m_vSubElem.resize(m_numSubElem);
    1414              : 
    1415              : //      get the multi indices for the sub elements and the boundary flags
    1416            0 :         bool* vIsBndElem = new bool[m_numSubElem];
    1417            0 :         std::vector<std::vector<int> > vElemBndSide(m_numSubElem);
    1418            0 :         std::vector<std::vector<MathVector<dim,int> > > vMultiIndex(m_numSubElem);
    1419            0 :         std::vector<std::vector<size_t> > vIndex(m_numSubElem);
    1420            0 :         ComputeMultiIndicesOfSubElement<dim>(&vMultiIndex[0], &vIsBndElem[0],
    1421              :                                              &vElemBndSide[0], &vIndex[0], m_roid, m_orderShape);
    1422              : 
    1423              : //      get reference element
    1424              :         try{
    1425              :         const DimReferenceElement<dim>& rRefElem
    1426            0 :                                 = ReferenceElementProvider::get<dim>(m_roid);
    1427              : 
    1428              : //      directions of counting
    1429            0 :         MathVector<dim> direction[dim];
    1430            0 :         for(int i = 0; i < dim; ++i){direction[i] = 0.0; direction[i][i] = 1.0;}
    1431              : 
    1432            0 :         for(size_t se = 0; se < m_numSubElem; ++se)
    1433              :         {
    1434            0 :                 for(size_t co = 0; co < vMultiIndex[se].size(); ++co)
    1435              :                 {
    1436              :                 //      compute corners of sub elem in local coordinates
    1437              :                         MathVector<dim> pos; pos = 0.0;
    1438            0 :                         for(int i = 0; i < dim; ++i)
    1439              :                         {
    1440            0 :                                 const number frac = vMultiIndex[se][co][i] / ((number)m_orderShape);
    1441              :                                 VecScaleAppend(pos, frac, direction[i]);
    1442              :                         }
    1443              :                         m_vSubElem[se].vvLocMid[0][co] = pos;
    1444              : 
    1445              :                 //      get multi index for corner
    1446            0 :                         m_vSubElem[se].vDoFID[co] = vIndex[se][co];
    1447              :                 }
    1448              : 
    1449              :         //      remember if boundary element
    1450            0 :                 m_vSubElem[se].isBndElem = vIsBndElem[se];
    1451              : 
    1452              :         //      remember boundary sides
    1453            0 :                 m_vSubElem[se].vElemBndSide = vElemBndSide[se];
    1454              :         }
    1455              : 
    1456            0 :         delete[] vIsBndElem;
    1457              : 
    1458              : //      compute mid points for all sub elements
    1459            0 :         for(size_t se = 0; se < m_numSubElem; ++se)
    1460              :                 ComputeMidPoints<dim, DimReferenceElement<dim>, maxMid>
    1461            0 :                                 (rRefElem, m_vSubElem[se].vvLocMid[0], m_vSubElem[se].vvLocMid);
    1462              : 
    1463              : //      number of scvf/scv per subelem
    1464            0 :         m_numSCVFPerSubElem = rRefElem.num(1);
    1465            0 :         m_numSCVPerSubElem = rRefElem.num(0);
    1466              : 
    1467            0 :         m_numSCVF = m_numSCVFPerSubElem * m_numSubElem;
    1468            0 :         m_numSCV = m_numSCVPerSubElem * m_numSubElem;
    1469              : 
    1470            0 :         m_vSCVF.resize(m_numSCVF);
    1471            0 :         m_vSCV.resize(m_numSCV);
    1472              : 
    1473              : 
    1474              : //      get trial space
    1475              :         const LocalShapeFunctionSet<dim>& rTrialSpace =
    1476            0 :                 LocalFiniteElementProvider::get<dim>(m_roid, m_lfeID);
    1477              : 
    1478              : //      request for quadrature rule
    1479              :         const ReferenceObjectID scvfRoid = scvf_type::REFERENCE_OBJECT_ID;
    1480              :         const QuadratureRule<dim-1>& rSCVFQuadRule
    1481            0 :                         = QuadratureRuleProvider<dim-1>::get(scvfRoid, m_quadOrderSCVF);
    1482              : 
    1483            0 :         const int nipSCVF = rSCVFQuadRule.size();
    1484            0 :         m_numSCVFIP = m_numSCVF * nipSCVF;
    1485              : 
    1486              : //      set up local informations for SubControlVolumeFaces (scvf)
    1487              : //      each scvf is associated to one edge of the sub-element
    1488            0 :         for(size_t i = 0; i < num_scvf(); ++i)
    1489              :         {
    1490              :         //      get corresponding subelement
    1491            0 :                 const size_t se = i / m_numSCVFPerSubElem;
    1492            0 :                 const size_t locSCVF = i % m_numSCVFPerSubElem;
    1493              : 
    1494              :         //      this scvf separates the given nodes
    1495            0 :                 const size_t locFrom =  rRefElem.id(1, locSCVF, 0, 0);
    1496            0 :                 const size_t locTo =  rRefElem.id(1, locSCVF, 0, 1);
    1497              : 
    1498            0 :                 m_vSCVF[i].From = m_vSubElem[se].vDoFID[locFrom];
    1499            0 :                 m_vSCVF[i].To = m_vSubElem[se].vDoFID[locTo];
    1500              : 
    1501              :         //      compute mid ids of the scvf
    1502            0 :                 ComputeSCVFMidID(rRefElem, m_vSCVF[i].vMidID, locSCVF);
    1503              : 
    1504              :         //      copy local corners of scvf
    1505              :                 CopyCornerByMidID<dim, maxMid>
    1506            0 :                         (m_vSCVF[i].vLocPos, m_vSCVF[i].vMidID, m_vSubElem[se].vvLocMid, SCVF::numCo);
    1507              : 
    1508              :         //      compute integration points
    1509            0 :                 m_vSCVF[i].vWeight = rSCVFQuadRule.weights();
    1510            0 :                 m_vSCVF[i].nip = nipSCVF;
    1511              : 
    1512            0 :                 m_vSCVF[i].vLocalIP.resize(nipSCVF);
    1513            0 :                 m_vSCVF[i].vGlobalIP.resize(nipSCVF);
    1514              : 
    1515            0 :                 m_vSCVF[i].vvShape.resize(nipSCVF);
    1516            0 :                 m_vSCVF[i].vvLocalGrad.resize(nipSCVF);
    1517            0 :                 m_vSCVF[i].vvGlobalGrad.resize(nipSCVF);
    1518            0 :                 m_vSCVF[i].vJtInv.resize(nipSCVF);
    1519            0 :                 m_vSCVF[i].vDetJ.resize(nipSCVF);
    1520            0 :                 m_vSCVF[i].vDetJMap.resize(nipSCVF);
    1521              : 
    1522            0 :                 m_vSCVF[i].nsh = rTrialSpace.num_sh();
    1523              : 
    1524            0 :                 ReferenceMapping<scvf_type, dim> map(m_vSCVF[i].vLocPos);
    1525            0 :                 for(size_t ip = 0; ip < rSCVFQuadRule.size(); ++ip)
    1526            0 :                         map.local_to_global(m_vSCVF[i].vLocalIP[ip], rSCVFQuadRule.point(ip));
    1527              :         }
    1528              : 
    1529              : 
    1530              : //      request for quadrature rule
    1531              :         static const ReferenceObjectID scvRoid = scv_type::REFERENCE_OBJECT_ID;
    1532              :         const QuadratureRule<dim>& rSCVQuadRule
    1533            0 :                         = QuadratureRuleProvider<dim>::get(scvRoid, m_quadOrderSCV);
    1534              : 
    1535            0 :         const int nipSCV = rSCVQuadRule.size();
    1536            0 :         m_numSCVIP = m_numSCV * nipSCV;
    1537              : 
    1538              : //      set up local informations for SubControlVolumes (scv)
    1539              : //      each scv is associated to one corner of the sub-element
    1540            0 :         for(size_t i = 0; i < num_scv(); ++i)
    1541              :         {
    1542              :         //      get corresponding subelement
    1543            0 :                 const size_t se = i / m_numSCVPerSubElem;
    1544            0 :                 const size_t locSCV = i % m_numSCVPerSubElem;
    1545              : 
    1546              :         //      store associated node
    1547            0 :                 m_vSCV[i].nodeId = m_vSubElem[se].vDoFID[locSCV];;
    1548              : 
    1549              :         //      compute mid ids scv
    1550            0 :                 ComputeSCVMidID(rRefElem, m_vSCV[i].vMidID, locSCV);
    1551              : 
    1552              :         //      copy local corners of scv
    1553              :                 CopyCornerByMidID<dim, maxMid>
    1554            0 :                         (m_vSCV[i].vLocPos, m_vSCV[i].vMidID, m_vSubElem[se].vvLocMid, m_vSCV[i].num_corners());
    1555              : 
    1556              :         //      compute integration points
    1557            0 :                 m_vSCV[i].vWeight = rSCVQuadRule.weights();
    1558            0 :                 m_vSCV[i].nip = nipSCV;
    1559              : 
    1560            0 :                 m_vSCV[i].vLocalIP.resize(nipSCV);
    1561            0 :                 m_vSCV[i].vGlobalIP.resize(nipSCV);
    1562              : 
    1563            0 :                 m_vSCV[i].vvShape.resize(nipSCV);
    1564            0 :                 m_vSCV[i].vvLocalGrad.resize(nipSCV);
    1565            0 :                 m_vSCV[i].vvGlobalGrad.resize(nipSCV);
    1566            0 :                 m_vSCV[i].vJtInv.resize(nipSCV);
    1567            0 :                 m_vSCV[i].vDetJ.resize(nipSCV);
    1568            0 :                 m_vSCV[i].vDetJMap.resize(nipSCV);
    1569              : 
    1570            0 :                 m_vSCV[i].nsh = rTrialSpace.num_sh();
    1571              : 
    1572            0 :                 ReferenceMapping<scv_type, dim> map(m_vSCV[i].vLocPos);
    1573            0 :                 for(size_t ip = 0; ip < rSCVQuadRule.size(); ++ip)
    1574            0 :                         map.local_to_global(m_vSCV[i].vLocalIP[ip], rSCVQuadRule.point(ip));
    1575              :         }
    1576              : 
    1577              :         /////////////////////////
    1578              :         // Shapes and Derivatives
    1579              :         /////////////////////////
    1580              : 
    1581            0 :         m_nsh = rTrialSpace.num_sh();
    1582              : 
    1583            0 :         for(size_t i = 0; i < num_scvf(); ++i)
    1584            0 :                 for(size_t ip = 0; ip < m_vSCVF[i].num_ip(); ++ip)
    1585              :                 {
    1586            0 :                         m_vSCVF[i].vvShape[ip].resize(m_vSCVF[i].nsh);
    1587            0 :                         m_vSCVF[i].vvLocalGrad[ip].resize(m_vSCVF[i].nsh);
    1588            0 :                         m_vSCVF[i].vvGlobalGrad[ip].resize(m_vSCVF[i].nsh);
    1589              : 
    1590            0 :                         rTrialSpace.shapes(&(m_vSCVF[i].vvShape[ip][0]), m_vSCVF[i].local_ip(ip));
    1591            0 :                         rTrialSpace.grads(&(m_vSCVF[i].vvLocalGrad[ip][0]), m_vSCVF[i].local_ip(ip));
    1592              :                 }
    1593              : 
    1594            0 :         for(size_t i = 0; i < num_scv(); ++i)
    1595            0 :                 for(size_t ip = 0; ip < m_vSCV[i].num_ip(); ++ip)
    1596              :                 {
    1597            0 :                         m_vSCV[i].vvShape[ip].resize(m_vSCV[i].nsh);
    1598            0 :                         m_vSCV[i].vvLocalGrad[ip].resize(m_vSCV[i].nsh);
    1599            0 :                         m_vSCV[i].vvGlobalGrad[ip].resize(m_vSCV[i].nsh);
    1600              : 
    1601            0 :                         rTrialSpace.shapes(&(m_vSCV[i].vvShape[ip][0]), m_vSCV[i].local_ip(ip));
    1602            0 :                         rTrialSpace.grads(&(m_vSCV[i].vvLocalGrad[ip][0]), m_vSCV[i].local_ip(ip));
    1603              :                 }
    1604              : 
    1605              :         }
    1606            0 :         UG_CATCH_THROW("DimFV1Geometry: update failed.");
    1607              : 
    1608              : //      copy ip positions in a list for Sub Control Volumes Faces (SCVF)
    1609            0 :         m_vLocSCVF_IP.resize(m_numSCVFIP);
    1610            0 :         m_vGlobSCVF_IP.resize(m_numSCVFIP);
    1611              :         size_t allIP = 0;
    1612            0 :         for(size_t i = 0; i < num_scvf(); ++i)
    1613            0 :                 for(size_t ip = 0; ip < m_vSCVF[i].num_ip(); ++ip)
    1614            0 :                         m_vLocSCVF_IP[allIP++] = scvf(i).local_ip(ip);
    1615              : 
    1616              : //      copy ip positions in a list for Sub Control Volumes (SCV)
    1617            0 :         m_vLocSCV_IP.resize(m_numSCVIP);
    1618            0 :         m_vGlobSCV_IP.resize(m_numSCVIP);
    1619              :         allIP = 0;
    1620            0 :         for(size_t i = 0; i < num_scv(); ++i)
    1621            0 :                 for(size_t ip = 0; ip < m_vSCV[i].num_ip(); ++ip)
    1622            0 :                         m_vLocSCV_IP[allIP++] = scv(i).local_ip(ip);
    1623            0 : }
    1624              : 
    1625              : 
    1626              : /// update data for given element
    1627              : template <int TWorldDim, int TDim>
    1628            0 : void DimFVGeometry<TWorldDim, TDim>::
    1629              : update(GridObject* pElem, const MathVector<worldDim>* vCornerCoords,
    1630              :        const LFEID& lfeID, size_t quadOrder,
    1631              :        const ISubsetHandler* ish)
    1632              : {
    1633              : //      If already update for this element, do nothing
    1634            0 :         if(m_pElem == pElem) return; else m_pElem = pElem;
    1635              : 
    1636              : //      get reference element type
    1637            0 :         ReferenceObjectID roid = (ReferenceObjectID)pElem->reference_object_id();
    1638              : 
    1639              : //      if already prepared for this roid, skip update of local values
    1640            0 :         if(m_roid != roid || lfeID != m_lfeID ||
    1641            0 :            (int)quadOrder != m_quadOrderSCVF || (int)quadOrder != m_quadOrderSCV)
    1642            0 :                         update_local(roid, lfeID, quadOrder);
    1643              : 
    1644              : //      get reference element mapping
    1645              :         try{
    1646              :         DimReferenceMapping<dim, worldDim>& rMapping
    1647            0 :                 = ReferenceMappingProvider::get<dim, worldDim>(roid);
    1648              : 
    1649              : //      update reference mapping
    1650            0 :         rMapping.update(vCornerCoords);
    1651              : 
    1652              : //      compute global informations for scvf
    1653            0 :         for(size_t i = 0; i < num_scvf(); ++i)
    1654              :         {
    1655              :         //      map local corners of scvf to global
    1656            0 :                 for(size_t co = 0; co < m_vSCVF[i].num_corners(); ++co)
    1657            0 :                         rMapping.local_to_global(m_vSCVF[i].vGloPos[co], m_vSCVF[i].vLocPos[co]);
    1658              : 
    1659              :         //      normal on scvf
    1660            0 :                 traits::NormalOnSCVF(m_vSCVF[i].Normal, m_vSCVF[i].vGloPos, vCornerCoords);
    1661            0 :                 VecNormalize(m_vSCVF[i].Normal, m_vSCVF[i].Normal);
    1662              : 
    1663              :                 static const ReferenceObjectID scvfRoid = scvf_type::REFERENCE_OBJECT_ID;
    1664              :                 const QuadratureRule<dim-1>& rSCVFQuadRule
    1665            0 :                                 = QuadratureRuleProvider<dim-1>::get(scvfRoid, m_quadOrderSCVF);
    1666            0 :                 ReferenceMapping<scvf_type, worldDim> map(m_vSCVF[i].vGloPos);
    1667              : 
    1668            0 :                 for(size_t ip = 0; ip < rSCVFQuadRule.size(); ++ip){
    1669            0 :                         m_vSCVF[i].vDetJMap[ip] = map.sqrt_gram_det(rSCVFQuadRule.point(ip));
    1670            0 :                         if(dim == 1) m_vSCVF[i].vDetJMap[ip] = 1.0;
    1671            0 :                         map.local_to_global(m_vSCVF[i].vGlobalIP[ip], rSCVFQuadRule.point(ip));
    1672              :                 }
    1673              : 
    1674            0 :                 rMapping.jacobian_transposed_inverse(&m_vSCVF[i].vJtInv[0], &m_vSCVF[i].vLocalIP[0], m_vSCVF[i].num_ip());
    1675            0 :                 rMapping.sqrt_gram_det(&m_vSCVF[i].vDetJ[0], &m_vSCVF[i].vLocalIP[0], m_vSCVF[i].num_ip());
    1676              :         }
    1677              : 
    1678              : //      compute size of scv
    1679            0 :         for(size_t i = 0; i < num_scv(); ++i)
    1680              :         {
    1681              :         //      map local corners of scvf to global
    1682            0 :                 rMapping.local_to_global(&m_vSCV[i].vGloPos[0], &m_vSCV[i].vLocPos[0], m_vSCV[i].num_corners());
    1683              : 
    1684            0 :                 rMapping.jacobian_transposed_inverse(&m_vSCV[i].vJtInv[0], &m_vSCV[i].vLocalIP[0], m_vSCV[i].num_ip());
    1685            0 :                 rMapping.sqrt_gram_det(&m_vSCV[i].vDetJ[0], &m_vSCV[i].vLocalIP[0], m_vSCV[i].num_ip());
    1686              : 
    1687              : 
    1688              :                 static const ReferenceObjectID scvRoid = scv_type::REFERENCE_OBJECT_ID;
    1689              :                 const QuadratureRule<dim>& rSCVQuadRule
    1690            0 :                                 = QuadratureRuleProvider<dim>::get(scvRoid, m_quadOrderSCV);
    1691              : 
    1692            0 :                 ReferenceMapping<scv_type, worldDim> map(m_vSCV[i].vGloPos);
    1693            0 :                 for(size_t ip = 0; ip < rSCVQuadRule.size(); ++ip){
    1694            0 :                         m_vSCV[i].vDetJMap[ip] = map.sqrt_gram_det(rSCVQuadRule.point(ip));
    1695            0 :                         map.local_to_global(m_vSCV[i].vGlobalIP[ip], rSCVQuadRule.point(ip));
    1696              :                 }
    1697              :         }
    1698              : 
    1699              :         }
    1700            0 :         UG_CATCH_THROW("DimFVGeometry: update failed.");
    1701              : 
    1702              : //      compute global gradients
    1703            0 :         for(size_t i = 0; i < num_scvf(); ++i)
    1704            0 :                 for(size_t ip = 0; ip < scvf(i).num_ip(); ++ip)
    1705            0 :                         for(size_t sh = 0 ; sh < m_vSCVF[i].nsh; ++sh)
    1706              :                                 MatVecMult(m_vSCVF[i].vvGlobalGrad[ip][sh], m_vSCVF[i].vJtInv[ip], m_vSCVF[i].vvLocalGrad[ip][sh]);
    1707              : 
    1708            0 :         for(size_t i = 0; i < num_scv(); ++i)
    1709            0 :                 for(size_t ip = 0; ip < scv(i).num_ip(); ++ip)
    1710            0 :                         for(size_t sh = 0 ; sh < m_vSCV[i].nsh; ++sh)
    1711              :                                 MatVecMult(m_vSCV[i].vvGlobalGrad[ip][sh], m_vSCV[i].vJtInv[ip], m_vSCV[i].vvLocalGrad[ip][sh]);
    1712              : 
    1713              : //      Copy ip pos in list for SCVF
    1714              :         size_t allIP = 0;
    1715            0 :         for(size_t i = 0; i < num_scvf(); ++i)
    1716            0 :                 for(size_t ip = 0; ip < scvf(i).num_ip(); ++ip)
    1717            0 :                         m_vGlobSCVF_IP[allIP++] = scvf(i).global_ip(ip);
    1718              : 
    1719              :         allIP = 0;
    1720            0 :         for(size_t i = 0; i < num_scv(); ++i)
    1721            0 :                 for(size_t ip = 0; ip < scv(i).num_ip(); ++ip)
    1722            0 :                         m_vGlobSCV_IP[allIP++] = scv(i).global_ip(ip);
    1723              : 
    1724              : //      if no boundary subsets required, return
    1725            0 :         if(num_boundary_subsets() == 0 || ish == NULL) return;
    1726            0 :         else update_boundary_faces(pElem, vCornerCoords, ish);
    1727              : }
    1728              : 
    1729              : template <int TWorldDim, int TDim>
    1730            0 : void DimFVGeometry<TWorldDim, TDim>::
    1731              : update_boundary_faces(GridObject* pElem, const MathVector<worldDim>* vCornerCoords, const ISubsetHandler* ish)
    1732              : {
    1733              : //      get grid
    1734            0 :         Grid& grid = *(ish->grid());
    1735              : 
    1736              : //      vector of subset indices of side
    1737              :         std::vector<int> vSubsetIndex;
    1738              : 
    1739              : //      get subset indices for sides (i.e. edge in 2d, faces in 3d)
    1740              :         if(dim == 1) {
    1741              :                 std::vector<Vertex*> vVertex;
    1742            0 :                 CollectVertices(vVertex, grid, pElem);
    1743            0 :                 vSubsetIndex.resize(vVertex.size());
    1744            0 :                 for(size_t i = 0; i < vVertex.size(); ++i)
    1745            0 :                         vSubsetIndex[i] = ish->get_subset_index(vVertex[i]);
    1746            0 :         }
    1747              :         if(dim == 2) {
    1748              :                 std::vector<Edge*> vEdges;
    1749            0 :                 CollectEdgesSorted(vEdges, grid, pElem);
    1750            0 :                 vSubsetIndex.resize(vEdges.size());
    1751            0 :                 for(size_t i = 0; i < vEdges.size(); ++i)
    1752            0 :                         vSubsetIndex[i] = ish->get_subset_index(vEdges[i]);
    1753            0 :         }
    1754              :         if(dim == 3) {
    1755              :                 std::vector<Face*> vFaces;
    1756            0 :                 CollectFacesSorted(vFaces, grid, pElem);
    1757            0 :                 vSubsetIndex.resize(vFaces.size());
    1758            0 :                 for(size_t i = 0; i < vFaces.size(); ++i)
    1759            0 :                         vSubsetIndex[i] = ish->get_subset_index(vFaces[i]);
    1760            0 :         }
    1761              : 
    1762              : //      get reference element mapping
    1763              :         try{
    1764              :         DimReferenceMapping<dim, worldDim>& rMapping
    1765            0 :                 = ReferenceMappingProvider::get<dim, worldDim>(m_roid);
    1766              : 
    1767              :         const DimReferenceElement<dim>& rRefElem
    1768            0 :                 = ReferenceElementProvider::get<dim>(m_roid);
    1769              : 
    1770              :         const ReferenceObjectID scvfRoid = scvf_type::REFERENCE_OBJECT_ID;
    1771              :         const QuadratureRule<dim-1>& rSCVFQuadRule
    1772            0 :                         = QuadratureRuleProvider<dim-1>::get(scvfRoid, m_quadOrderSCVF);
    1773              : 
    1774              :         const LocalShapeFunctionSet<dim>& rTrialSpace =
    1775            0 :                 LocalFiniteElementProvider::get<dim>(m_roid, LFEID(LFEID::LAGRANGE, dim, m_orderShape));
    1776              : 
    1777              : //      update reference mapping
    1778            0 :         rMapping.update(vCornerCoords);
    1779              : 
    1780              : //      loop requested subset
    1781              :         typename std::map<int, std::vector<BF> >::iterator it;
    1782            0 :         for (it=m_mapVectorBF.begin() ; it != m_mapVectorBF.end(); ++it)
    1783              :         {
    1784              :         //      get subset index
    1785            0 :                 const int bndIndex = (*it).first;
    1786              : 
    1787              :         //      get vector of BF for element
    1788            0 :                 std::vector<BF>& vBF = (*it).second;
    1789              : 
    1790              :         //      clear vector
    1791              :                 vBF.clear();
    1792              : 
    1793              :         //      current number of bf
    1794              :                 size_t curr_bf = 0;
    1795              : 
    1796              :         //      loop subelements
    1797            0 :                 for(size_t se = 0; se < m_numSubElem; ++se)
    1798              :                 {
    1799              :                 //      skip inner sub elements
    1800            0 :                         if(!m_vSubElem[se].isBndElem) continue;
    1801              : 
    1802              :                 //      loop sides of element
    1803            0 :                         for(size_t side = 0; side < m_vSubElem[se].vElemBndSide.size(); ++side)
    1804              :                         {
    1805              :                         //      get whole element bnd side
    1806            0 :                                 const int elemBndSide = m_vSubElem[se].vElemBndSide[side];
    1807              : 
    1808              :                         //      skip non boundary sides
    1809            0 :                                 if(elemBndSide == -1 || vSubsetIndex[elemBndSide] != bndIndex) continue;
    1810              : 
    1811              :                         //      number of corners of side
    1812            0 :                                 const int coOfSide = rRefElem.num(dim-1, elemBndSide, 0);
    1813              : 
    1814              :                         //      compute global mids for vertices on this subelem
    1815              :                         //      (needed to calculate normal - at least if dim < worldDim)
    1816            0 :                                 for (size_t m = 0; m < (size_t) maxMid; ++m)
    1817            0 :                                         rMapping.local_to_global(m_vSubElem[se].vvGloMid[0][m], m_vSubElem[se].vvLocMid[0][m]);
    1818              : 
    1819              :                         //      resize vector
    1820            0 :                                 vBF.resize(curr_bf + coOfSide);
    1821              : 
    1822              :                         //      loop corners
    1823            0 :                                 for(int co = 0; co < coOfSide; ++co)
    1824              :                                 {
    1825              :                                 //      get current bf
    1826              :                                         BF& bf = vBF[curr_bf];
    1827              : 
    1828              :                                 //      set node id == scv this bf belongs to
    1829            0 :                                         const int refNodeId = rRefElem.id(dim-1, elemBndSide, 0, co);
    1830            0 :                                         bf.nodeId = m_vSubElem[se].vDoFID[refNodeId];
    1831              : 
    1832              :                                 //      Compute MidID for BF
    1833            0 :                                         ComputeBFMidID(rRefElem, elemBndSide, bf.vMidID, co);
    1834              : 
    1835              :                                 //      copy local corners of bf
    1836              :                                         CopyCornerByMidID<dim, maxMid>
    1837            0 :                                                 (bf.vLocPos, bf.vMidID, m_vSubElem[se].vvLocMid, BF::numCo);
    1838              : //                                      CopyCornerByMidID<worldDim, maxMid>
    1839              : //                                              (bf.vGloPos, bf.vMidID, m_vSubElem[se].vvGloMid, BF::numCo);
    1840              : 
    1841              :                                 //      compute global corners of bf
    1842            0 :                                         for(size_t i = 0; i < bf.num_corners(); ++i)
    1843            0 :                                                 rMapping.local_to_global(bf.vGloPos[i], bf.vLocPos[i]);
    1844              : 
    1845              :                                 //      normal on bf
    1846            0 :                                         traits::NormalOnSCVF(bf.Normal, bf.vGloPos, m_vSubElem[se].vvGloMid[0]);
    1847              : 
    1848              :                                 //      compute volume
    1849            0 :                                         bf.Vol = VecTwoNorm(bf.Normal);
    1850              : 
    1851              :                                 //      compute local integration points
    1852            0 :                                         bf.vWeight = rSCVFQuadRule.weights();
    1853            0 :                                         bf.nip = rSCVFQuadRule.size();
    1854            0 :                                         bf.vLocalIP.resize(bf.nip);
    1855            0 :                                         bf.vGlobalIP.resize(bf.nip);
    1856              : 
    1857            0 :                                         ReferenceMapping<scvf_type, dim> map(bf.vLocPos);
    1858            0 :                                         for(size_t ip = 0; ip < rSCVFQuadRule.size(); ++ip)
    1859            0 :                                                 map.local_to_global(bf.vLocalIP[ip], rSCVFQuadRule.point(ip));
    1860              : 
    1861              :                                 //      compute global integration points
    1862            0 :                                         for(size_t ip = 0; ip < bf.num_ip(); ++ip)
    1863            0 :                                                 rMapping.local_to_global(bf.vGlobalIP[ip], bf.vLocalIP[ip]);
    1864              : 
    1865            0 :                                         bf.nsh = rTrialSpace.num_sh();
    1866            0 :                                         bf.vvShape.resize(bf.nip);
    1867            0 :                                         bf.vvLocalGrad.resize(bf.nip);
    1868            0 :                                         bf.vvGlobalGrad.resize(bf.nip);
    1869            0 :                                         bf.vJtInv.resize(bf.nip);
    1870            0 :                                         bf.vDetJ.resize(bf.nip);
    1871            0 :                                         for(size_t ip = 0; ip < bf.num_ip(); ++ip)
    1872              :                                         {
    1873            0 :                                                 bf.vvShape[ip].resize(bf.nsh);
    1874            0 :                                                 bf.vvLocalGrad[ip].resize(bf.nsh);
    1875            0 :                                                 bf.vvGlobalGrad[ip].resize(bf.nsh);
    1876              :                                         }
    1877              : 
    1878              :                                 //      compute shapes and gradients
    1879            0 :                                         for(size_t ip = 0; ip < bf.num_ip(); ++ip)
    1880              :                                         {
    1881            0 :                                                 rTrialSpace.shapes(&(bf.vvShape[ip][0]), bf.local_ip(ip));
    1882            0 :                                                 rTrialSpace.grads(&(bf.vvLocalGrad[ip][0]), bf.local_ip(ip));
    1883              :                                         }
    1884              : 
    1885            0 :                                         rMapping.jacobian_transposed_inverse(&bf.vJtInv[0], &bf.vLocalIP[0], bf.num_ip());
    1886            0 :                                         rMapping.sqrt_gram_det(&bf.vDetJ[0], &bf.vLocalIP[0], bf.num_ip());
    1887              : 
    1888              :                                 //      compute global gradient
    1889            0 :                                         for(size_t ip = 0; ip < bf.num_ip(); ++ip)
    1890            0 :                                                 for(size_t sh = 0 ; sh < bf.num_sh(); ++sh)
    1891              :                                                         MatVecMult(bf.vvGlobalGrad[ip][sh],
    1892              :                                                                    bf.vJtInv[ip], bf.vvLocalGrad[ip][sh]);
    1893              : 
    1894              :                                 //      increase curr_bf
    1895            0 :                                         ++curr_bf;
    1896              :                                 }
    1897              :                         }
    1898              :                 }
    1899              :         }
    1900              : 
    1901              :         }
    1902            0 :         UG_CATCH_THROW("DimFVGeometry: update failed.");
    1903            0 : }
    1904              : 
    1905              : //////////////////////
    1906              : // FVGeometry
    1907              : #ifdef UG_DIM_1
    1908              :         template class DimFVGeometry<1, 1>;
    1909              : #endif
    1910              : 
    1911              : #ifdef UG_DIM_2
    1912              :         template class FVGeometry<1, RegularEdge, 2>;
    1913              :         template class FVGeometry<1, Triangle, 2>;
    1914              :         template class FVGeometry<1, Quadrilateral, 2>;
    1915              :         template class FVGeometry<2, RegularEdge, 2>;
    1916              :         template class FVGeometry<2, Triangle, 2>;
    1917              :         template class FVGeometry<2, Quadrilateral, 2>;
    1918              :         template class FVGeometry<3, RegularEdge, 2>;
    1919              :         template class FVGeometry<3, Triangle, 2>;
    1920              :         template class FVGeometry<3, Quadrilateral, 2>;
    1921              : 
    1922              :         template class DimFVGeometry<2, 2>;
    1923              :         template class DimFVGeometry<2, 1>;
    1924              : #endif
    1925              : 
    1926              : #ifdef UG_DIM_3
    1927              :         template class FVGeometry<1, RegularEdge, 3>;
    1928              :         template class FVGeometry<1, Tetrahedron, 3>;
    1929              :         template class FVGeometry<1, Prism, 3>;
    1930              :         template class FVGeometry<1, Hexahedron, 3>;
    1931              :         template class FVGeometry<2, RegularEdge, 3>;
    1932              :         template class FVGeometry<2, Tetrahedron, 3>;
    1933              :         template class FVGeometry<2, Prism, 3>;
    1934              :         template class FVGeometry<2, Hexahedron, 3>;
    1935              :         template class FVGeometry<3, RegularEdge, 3>;
    1936              :         template class FVGeometry<3, Tetrahedron, 3>;
    1937              :         template class FVGeometry<3, Prism, 3>;
    1938              :         template class FVGeometry<3, Hexahedron, 3>;
    1939              : 
    1940              :         template class DimFVGeometry<3, 3>;
    1941              :         template class DimFVGeometry<3, 2>;
    1942              :         template class DimFVGeometry<3, 1>;
    1943              : #endif
    1944              : 
    1945              : } // end namespace ug
        

Generated by: LCOV version 2.0-1