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

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2012-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Christian Wehner
       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              :  * Node centered finite volume geometry for Crouzeix-Raviart-Elements
      35              :  */
      36              : 
      37              : #include "common/util/provider.h"
      38              : #include "fvcr_geom.h"
      39              : #include "lib_disc/reference_element/reference_element.h"
      40              : #include "lib_disc/reference_element/reference_mapping.h"
      41              : #include "lib_disc/reference_element/reference_mapping_provider.h"
      42              : #include "lib_disc/quadrature/quadrature.h"
      43              : 
      44              : namespace ug{
      45              : 
      46              : ////////////////////////////////////////////////////////////////////////////////
      47              : ////////////////////////////////////////////////////////////////////////////////
      48              : // Dim-dependent Crouzeix-Raviart Finite Volume Geometry
      49              : ////////////////////////////////////////////////////////////////////////////////
      50              : ////////////////////////////////////////////////////////////////////////////////
      51              : 
      52              : template <int TDim, int TWorldDim>
      53            0 : void DimCRFVGeometry<TDim, TWorldDim>::
      54              : update_local_data()
      55              : {
      56              : //      get reference element
      57              :         try{
      58              :         m_rRefElem
      59            0 :                 = ReferenceElementProvider::get<dim>(m_roid);
      60              : 
      61              : //      set number of scvf / scv of this roid
      62            0 :         m_numSCV = m_rRefElem.num(dim-1); // number of faces
      63            0 :         m_numSCVF = m_rRefElem.num(1); // number of edges
      64              : 
      65              : //  compute barycenter coordinates
      66              :         localBary = m_rRefElem.corner(0);
      67            0 :         for (size_t j=1;j<m_rRefElem.num(0);j++){
      68              :                 localBary+=m_rRefElem.corner(j);
      69              :         }
      70            0 :         localBary*=1./(number)m_rRefElem.num(0);
      71              : 
      72              : //      set up local informations for SubControlVolumeFaces (scvf)
      73              : //      each scvf is associated to one vertex (2d) / edge (3d) of the element
      74            0 :         for(size_t i = 0; i < m_numSCVF; ++i)
      75              :         {
      76              :         //      this scvf separates the given edges/faces
      77            0 :                 m_vSCVF[i].From = m_rRefElem.id(dim-2, i, dim-1, 0);// todo handle dim==1
      78            0 :                 m_vSCVF[i].To = m_rRefElem.id(dim-2, i, dim-1, 1);
      79              : 
      80            0 :                 for (size_t j=0;j<m_vSCVF[i].numCo-1;j++){
      81            0 :                         m_vSCVF[i].vLocPos[j]=m_rRefElem.corner(m_rRefElem.id(dim-2,i,0,j));
      82              :                 }
      83              : 
      84              :                 m_vSCVF[i].vLocPos[m_vSCVF[i].numCo-1]=localBary;
      85            0 :                 AveragePositions(m_vSCVF[i].localIP, m_vSCVF[i].vLocPos, m_vSCVF[i].numCo);
      86              :         }
      87              : 
      88              : //      set up local informations for SubControlVolumes (scv)
      89              : //      each scv is associated to one edge(2d) / face(3d) of the element
      90            0 :         for(size_t i = 0; i < m_numSCV; ++i)
      91              :         {
      92              :         //      store associated node
      93            0 :                 m_vSCV[i].nodeID = i;
      94              : 
      95            0 :                 m_vSCV[i].numCorners = m_rRefElem.num(dim-1,i,0)+1;
      96            0 :                 for (int j=0;j<m_vSCV[i].numCorners-1;j++){
      97            0 :                         m_vSCV[i].vLocPos[m_vSCV[i].numCorners-2-j]=m_rRefElem.corner(m_rRefElem.id(dim-1,i,0,j));
      98              :                 }
      99            0 :                 AveragePositions(m_vLocUnkCoords[i], m_vSCV[i].vLocPos, m_vSCV[i].numCorners-1);
     100              :                 m_vSCV[i].vLocIP = m_vLocUnkCoords[i];
     101              :                 m_vSCV[i].vLocPos[m_vSCV[i].numCorners-1]=localBary;
     102              :         }
     103              : 
     104              :         /////////////////////////
     105              :         // Shapes and Derivatives
     106              :         /////////////////////////
     107              : 
     108              :         const LocalShapeFunctionSet<dim>& rTrialSpace =
     109            0 :                 LocalFiniteElementProvider::get<dim>(m_roid, LFEID(LFEID::CROUZEIX_RAVIART, dim, 1));
     110              : 
     111            0 :         m_nsh = rTrialSpace.num_sh();
     112              : 
     113            0 :         for(size_t i = 0; i < m_numSCVF; ++i)
     114              :         {
     115            0 :                 m_vSCVF[i].numSH = rTrialSpace.num_sh();
     116            0 :                 rTrialSpace.shapes(&(m_vSCVF[i].vShape[0]), m_vSCVF[i].local_ip());
     117            0 :                 rTrialSpace.grads(&(m_vSCVF[i].vLocalGrad[0]), m_vSCVF[i].local_ip());
     118              :         }
     119              : 
     120            0 :         for(size_t i = 0; i < m_numSCV; ++i)
     121              :         {
     122            0 :                 m_vSCV[i].numSH = rTrialSpace.num_sh();
     123            0 :                 rTrialSpace.shapes(&(m_vSCV[i].vShape[0]), m_vSCV[i].local_ip());
     124            0 :                 rTrialSpace.grads(&(m_vSCV[i].vLocalGrad[0]), m_vSCV[i].local_ip());
     125              :         }
     126              : 
     127              :         }
     128            0 :         UG_CATCH_THROW("DimCRFVGeometry: update failed.");
     129              : 
     130              : //      copy ip positions in a list for Sub Control Volumes Faces (SCVF)
     131            0 :         for(size_t i = 0; i < m_numSCVF; ++i)
     132              :                 m_vLocSCVF_IP[i] = scvf(i).local_ip();
     133              :                 
     134            0 :         m_numConstrainedDofs = 0;
     135            0 :         m_numConstrainedSCVF = 0;
     136            0 : }
     137              : 
     138              : 
     139              : /// update data for given element
     140              : template <int TDim, int TWorldDim>
     141            0 : void DimCRFVGeometry<TDim, TWorldDim>::
     142              : update(GridObject* pElem, const MathVector<worldDim>* vCornerCoords, const ISubsetHandler* ish)
     143              : {
     144              : //      If already update for this element, do nothing
     145            0 :         if(m_pElem == pElem) return; else m_pElem = pElem;
     146              : 
     147              : //      refresh local data, if different roid given
     148            0 :         if(m_roid != pElem->reference_object_id())
     149              :         {
     150              :         //      remember new roid
     151            0 :                 m_roid = (ReferenceObjectID) pElem->reference_object_id();
     152              : 
     153              :         //      update local data
     154            0 :                 update_local_data();
     155              :         }
     156              : 
     157              : //      get reference element
     158              :         try{
     159              :         const DimReferenceElement<dim>& m_rRefElem
     160            0 :                 = ReferenceElementProvider::get<dim>(m_roid);
     161              : 
     162              :         //  compute barycenter coordinates
     163              :         globalBary = vCornerCoords[0];
     164            0 :         for (size_t j=1;j<m_rRefElem.num(0);j++){
     165            0 :            globalBary+=vCornerCoords[j];
     166              :         }
     167            0 :         globalBary*=1./(number)m_rRefElem.num(0);
     168              : 
     169              : //      compute global informations for scvf
     170            0 :         for(size_t i = 0; i < num_scvf(); ++i)
     171              :         {
     172            0 :                 for (size_t j=0;j<m_vSCVF[i].numCo-1;j++){
     173            0 :                         m_vSCVF[i].vGloPos[j]=vCornerCoords[m_rRefElem.id(dim-2,i,0,j)];
     174              :                 }
     175              :                 m_vSCVF[i].vGloPos[m_vSCVF[i].numCo-1]=globalBary;
     176            0 :                 AveragePositions(m_vSCVF[i].globalIP, m_vSCVF[i].vGloPos, m_vSCVF[i].numCo);
     177            0 :                 ElementNormal<face_type0,worldDim>(m_vSCVF[i].Normal,m_vSCVF[i].vGloPos);// face_type0 identical to scvf type
     178              :         }
     179              : 
     180              : //      compute size of scv
     181            0 :         for(size_t i = 0; i < num_scv(); ++i)
     182              :         {
     183              :                 // side nodes in reverse order to fulfill standard element order
     184            0 :                 for (int j=0;j<m_vSCV[i].numCorners-1;j++){
     185            0 :                         m_vSCV[i].vGloPos[m_vSCV[i].numCorners-2-j]=vCornerCoords[m_rRefElem.id(dim-1,i,0,j)];
     186              :                 }
     187            0 :                 AveragePositions(m_vGlobUnkCoords[i], m_vSCV[i].vGloPos, m_vSCV[i].numCorners-1);
     188              :                 m_vSCV[i].vGlobIP = m_vGlobUnkCoords[i];
     189              :                 
     190              :                 m_vSCV[i].vGloPos[m_vSCV[i].numCorners-1]=globalBary;
     191              :                 //      compute volume of scv and normal to associated element face
     192              :                 //CRSCVSizeAndNormal<dim>(m_vSCV[i].Vol,m_vSCV[i].Normal,m_vSCV[i].vGloPos,m_vSCV[i].numCorners);
     193            0 :                 if (m_vSCV[i].numCorners-1==dim){
     194            0 :                      m_vSCV[i].Vol = ElementSize<scv_type0,worldDim>(m_vSCV[i].vGloPos);
     195            0 :                      ElementNormal<face_type0, worldDim>(m_vSCV[i].Normal, m_vSCV[i].vGloPos);
     196              :                 } else { // m_vSCV[i].numCorners-2==dim , only possible in 3d (pyramid)
     197            0 :                      m_vSCV[i].Vol = ElementSize<scv_type1,worldDim>(m_vSCV[i].vGloPos);
     198            0 :                      ElementNormal<face_type1,worldDim>(m_vSCV[i].Normal, m_vSCV[i].vGloPos);
     199              :                 };
     200              :                 // nodes are in reverse order therefore reverse sign to get outward normal
     201              :                 m_vSCV[i].Normal*=-1;
     202              :         }
     203              : 
     204              : //      get reference mapping
     205            0 :         DimReferenceMapping<dim, worldDim>& rMapping = ReferenceMappingProvider::get<dim, worldDim>(m_roid);
     206            0 :         rMapping.update(vCornerCoords);
     207              : 
     208              :         //\todo compute with on virt. call
     209              : //      compute jacobian for linear mapping
     210            0 :         if(rMapping.is_linear())
     211              :         {
     212              :                 MathMatrix<worldDim,dim> JtInv;
     213            0 :                 rMapping.jacobian_transposed_inverse(JtInv, m_vSCVF[0].local_ip());
     214            0 :                 const number detJ = rMapping.sqrt_gram_det(m_vSCVF[0].local_ip());
     215              : 
     216            0 :                 for(size_t i = 0; i < num_scvf(); ++i)
     217              :                 {
     218              :                         m_vSCVF[i].JtInv = JtInv;
     219            0 :                         m_vSCVF[i].detj = detJ;
     220              :                 }
     221              : 
     222            0 :                 for(size_t i = 0; i < num_scv(); ++i)
     223              :                 {
     224              :                         m_vSCV[i].JtInv = JtInv;
     225            0 :                         m_vSCV[i].detj = detJ;
     226              :                 }
     227              :         }
     228              : //      else compute jacobian for each integration point
     229              :         else
     230              :         {
     231            0 :                 for(size_t i = 0; i < num_scvf(); ++i)
     232              :                 {
     233            0 :                         rMapping.jacobian_transposed_inverse(m_vSCVF[i].JtInv, m_vSCVF[i].local_ip());
     234            0 :                         m_vSCVF[i].detj = rMapping.sqrt_gram_det(m_vSCVF[i].local_ip());
     235              :                 }
     236            0 :                 for(size_t i = 0; i < num_scv(); ++i)
     237              :                 {
     238            0 :                         rMapping.jacobian_transposed_inverse(m_vSCV[i].JtInv, m_vSCV[i].local_ip());
     239            0 :                         m_vSCV[i].detj = rMapping.sqrt_gram_det(m_vSCV[i].local_ip());
     240              :                 }
     241              :         }
     242              : 
     243              : //      compute global gradients
     244            0 :         for(size_t i = 0; i < num_scvf(); ++i)
     245            0 :                 for(size_t sh = 0; sh < scvf(i).num_sh(); ++sh)
     246              :                         MatVecMult(m_vSCVF[i].vGlobalGrad[sh], m_vSCVF[i].JtInv, m_vSCVF[i].vLocalGrad[sh]);
     247              : 
     248            0 :         for(size_t i = 0; i < num_scv(); ++i)
     249            0 :                 for(size_t sh = 0; sh < scv(i).num_sh(); ++sh)
     250              :                         MatVecMult(m_vSCV[i].vGlobalGrad[sh], m_vSCV[i].JtInv, m_vSCV[i].vLocalGrad[sh]);
     251              : 
     252              : //      copy ip points in list (SCVF)
     253            0 :         for(size_t i = 0; i < num_scvf(); ++i)
     254              :                 m_vGlobSCVF_IP[i] = scvf(i).global_ip();
     255              : 
     256              :         }
     257            0 :         UG_CATCH_THROW("DimCRFVGeometry: update failed.");
     258              : 
     259              : //      if no boundary subsets required, return
     260            0 :         if(num_boundary_subsets() == 0 || ish == NULL) return;
     261            0 :         else update_boundary_faces(pElem, vCornerCoords, ish);
     262              : }
     263              : 
     264              : /// update data checking for hanging nodes for given element
     265              : template <int TDim, int TWorldDim>
     266            0 : void DimCRFVGeometry<TDim, TWorldDim>::
     267              : update_hanging(GridObject* pElem, const MathVector<worldDim>* vCornerCoords, const ISubsetHandler* ish,bool keepSCV,bool keepSCVF)
     268              : {
     269              : //      If already update for this element, do nothing
     270            0 :         if(m_pElem == pElem) return; else m_pElem = pElem;
     271              :         
     272              : //  get grid
     273            0 :         Grid& grid = *(ish->grid());
     274              : 
     275              : //      refresh local data, if different roid given
     276            0 :         if(m_roid != pElem->reference_object_id())
     277              :         {
     278              :         //      remember new roid
     279            0 :                 m_roid = (ReferenceObjectID) pElem->reference_object_id();
     280              : 
     281              :         //      update local data
     282            0 :                 update_local_data();
     283              :                 
     284            0 :                 m_numDofs       = num_scv();
     285              :         }
     286              :         
     287              :         const LocalShapeFunctionSet<dim>& rTrialSpace =
     288            0 :                                 LocalFiniteElementProvider::get<dim>(m_roid, LFEID(LFEID::CROUZEIX_RAVIART, dim, 1));
     289              : 
     290              :         //  compute barycenter coordinates
     291              :         globalBary = vCornerCoords[0];
     292            0 :         for (size_t j=1;j<m_rRefElem.num(0);j++){
     293            0 :            globalBary+=vCornerCoords[j];
     294              :         }
     295            0 :         globalBary*=1./(number)m_rRefElem.num(0);
     296              : 
     297              : //      compute global informations for scvf
     298            0 :         for(size_t i = 0; i < num_scvf(); ++i)
     299              :         {
     300            0 :                 for (size_t j=0;j<m_vSCVF[i].numCo-1;j++){
     301            0 :                         m_vSCVF[i].vGloPos[j]=vCornerCoords[m_rRefElem.id(dim-2,i,0,j)];
     302              :                 }
     303              :                 m_vSCVF[i].vGloPos[m_vSCVF[i].numCo-1]=globalBary;
     304            0 :                 AveragePositions(m_vSCVF[i].globalIP, m_vSCVF[i].vGloPos, m_vSCVF[i].numCo);
     305            0 :                 ElementNormal<face_type0,worldDim>(m_vSCVF[i].Normal,m_vSCVF[i].vGloPos);// face_type0 identical to scvf type
     306              :         }
     307              : 
     308              : //      compute size of scv
     309            0 :         for(size_t i = 0; i < num_scv(); ++i)
     310              :         {
     311              :                 // side nodes in reverse order to fulfill standard element order
     312            0 :                 for (int j=0;j<m_vSCV[i].numCorners-1;j++){
     313            0 :                         m_vSCV[i].vGloPos[m_vSCV[i].numCorners-2-j]=vCornerCoords[m_rRefElem.id(dim-1,i,0,j)];
     314              :                 }
     315            0 :                 AveragePositions(m_vGlobUnkCoords[i], m_vSCV[i].vGloPos, m_vSCV[i].numCorners-1);
     316              :                 m_vSCV[i].vGlobIP = m_vGlobUnkCoords[i];
     317              :                 
     318              :                 m_vSCV[i].vGloPos[m_vSCV[i].numCorners-1]=globalBary;
     319              :                 //      compute volume of scv and normal to associated element face
     320              :                 //CRSCVSizeAndNormal<dim>(m_vSCV[i].Vol,m_vSCV[i].Normal,m_vSCV[i].vGloPos,m_vSCV[i].numCorners);
     321            0 :                 if (m_vSCV[i].numCorners-1==dim){
     322            0 :                      m_vSCV[i].Vol = ElementSize<scv_type0,worldDim>(m_vSCV[i].vGloPos);
     323            0 :                      ElementNormal<face_type0, worldDim>(m_vSCV[i].Normal, m_vSCV[i].vGloPos);
     324              :                 } else { // m_vSCV[i].numCorners-2==dim , only possible in 3d (pyramid)
     325            0 :                      m_vSCV[i].Vol = ElementSize<scv_type1,worldDim>(m_vSCV[i].vGloPos);
     326            0 :                      ElementNormal<face_type1,worldDim>(m_vSCV[i].Normal, m_vSCV[i].vGloPos);
     327              :                 };
     328              :                 // nodes are in reverse order therefore reverse sign to get outward normal
     329              :                 m_vSCV[i].Normal*=-1;
     330              :         }
     331              :         
     332              :         //      get reference mapping
     333            0 :         DimReferenceMapping<dim, worldDim>& rMapping = ReferenceMappingProvider::get<dim, worldDim>(m_roid);
     334            0 :         rMapping.update(vCornerCoords);
     335              :         
     336              :         //  check for hanging nodes
     337              :         if (dim==2){
     338              :                 std::vector<Edge*> vEdges;
     339            0 :                 CollectEdgesSorted(vEdges, grid, pElem);
     340            0 :                 for(size_t side = 0; side < vEdges.size(); ++side){
     341            0 :                         ConstrainingEdge* constrainingObj = dynamic_cast<ConstrainingEdge*>(vEdges[side]);
     342            0 :                         if(constrainingObj == NULL) continue;
     343              :                         
     344              :                         // found constraining edge
     345              :                         MathVector<worldDim> globalMidpoint = m_vSCV[side].vGlobIP;
     346              :                         MathVector<dim> localMidpoint = m_vSCV[side].vLocIP;
     347              :                         // get edge corners
     348              :                         size_t edgeCo[2];
     349            0 :                         for (size_t j=0;j<2;j++) edgeCo[j] = m_rRefElem.id(1,side,0,j);
     350              :                         // compute dof positions on constraining edge,
     351              :                         // replace dof "side" with first and insert second at the end
     352              :                         // set up new scvs
     353              :                         // keepSCV parameter specifies if scv "side" gets replaced by new one
     354              :                         size_t ind=side;
     355              :                         size_t keepOffset=0;
     356              :                         MathVector<worldDim> normal = m_vSCV[side].Normal;
     357              :                         normal*=0.5;
     358            0 :                         number vol    = 0.5*m_vSCV[side].Vol;
     359            0 :                         if (keepSCV){ 
     360            0 :                                 ind=m_numSCV+1;
     361              :                                 keepOffset=1;
     362              :                         }
     363            0 :                         for (int d=0;d<worldDim;d++)
     364            0 :                                 m_vGlobUnkCoords[ind][d] = 0.5 * (vCornerCoords[edgeCo[0]][d] + globalMidpoint[d]);
     365            0 :                         for (int d=0;d<dim;d++)
     366            0 :                                 m_vLocUnkCoords[ind][d] = 0.5 * (m_rRefElem.corner(edgeCo[0])[d] + localMidpoint[d]);
     367            0 :                         for (int d=0;d<worldDim;d++)
     368            0 :                                 m_vGlobUnkCoords[m_numSCV][d] = 0.5 * (vCornerCoords[edgeCo[1]][d] + globalMidpoint[d]);
     369            0 :                         for (int d=0;d<dim;d++)
     370            0 :                                 m_vLocUnkCoords[m_numSCV][d] = 0.5 * (m_rRefElem.corner(edgeCo[1])[d] + localMidpoint[d]);
     371              :                         // handle corresponding scvfs
     372              :                         // if keepSCVF copy them into constrained scvf array
     373            0 :                         if (keepSCVF){
     374            0 :                                 for (size_t j=0;j<2;j++){
     375            0 :                                         m_vConstrainedSCVF[m_numConstrainedSCVF+j] = m_vSCVF[edgeCo[j]];
     376            0 :                                         if (m_vConstrainedSCVF[edgeCo[j]].To==side){
     377            0 :                                                 m_vConstrainedSCVF[edgeCo[j]].From=side;
     378              :                                                 m_vConstrainedSCVF[edgeCo[j]].Normal*=-1;
     379              :                                         }
     380              :                                 }
     381            0 :                                 m_numConstrainedSCVF += 2;
     382              :                         }
     383            0 :                         for (size_t j=0;j<2;j++){
     384            0 :                                 if (m_vSCVF[edgeCo[j]].From==side) m_vSCVF[edgeCo[j]].From=m_numDofs+j;
     385            0 :                                 if (m_vSCVF[edgeCo[j]].To==side) m_vSCVF[edgeCo[j]].To=m_numDofs+j;
     386              :                         }
     387              :                         m_vSCV[ind].Normal = normal;
     388            0 :                         m_vSCV[ind].Vol = vol;
     389            0 :                         m_vSCV[ind].nodeID = m_numDofs;
     390              :                         m_vSCV[ind].vGlobIP = m_vGlobUnkCoords[ind];
     391              :                         m_vSCV[ind].vLocIP = m_vLocUnkCoords[ind];
     392            0 :                         m_vSCV[ind].numSH = rTrialSpace.num_sh();
     393            0 :                         m_vSCV[ind].vGloPos[0]=vCornerCoords[edgeCo[0]];
     394              :                         m_vSCV[ind].vGloPos[1]=globalMidpoint;
     395              :                         m_vSCV[ind].vGloPos[2]=globalBary;
     396              :                         m_vSCV[ind].vLocPos[0]=m_rRefElem.corner(edgeCo[0]);
     397              :                         m_vSCV[ind].vLocPos[1]=localMidpoint;
     398              :                         m_vSCV[ind].vLocPos[2]=localBary;
     399            0 :                         m_vSCV[ind].numCorners = 3;
     400            0 :                         rTrialSpace.shapes(&(m_vSCV[ind].vShape[0]), m_vSCV[ind].local_ip());
     401            0 :                         rTrialSpace.grads(&(m_vSCV[ind].vLocalGrad[0]), m_vSCV[ind].local_ip());
     402              :                         // second scv inserted at the end
     403            0 :                         m_vSCV[m_numSCV].Normal = normal;
     404            0 :                         m_vSCV[m_numSCV].Vol = vol;
     405            0 :                         m_vSCV[m_numSCV].nodeID = m_numDofs+1;
     406              :                         m_vSCV[m_numSCV].vGlobIP = m_vGlobUnkCoords[m_numSCV];
     407              :                         m_vSCV[m_numSCV].vLocIP = m_vLocUnkCoords[m_numSCV];
     408            0 :                         m_vSCV[m_numSCV].numSH = rTrialSpace.num_sh();
     409            0 :                         m_vSCV[m_numSCV].vGloPos[0]=vCornerCoords[edgeCo[1]];
     410              :                         m_vSCV[m_numSCV].vGloPos[1]=globalMidpoint;
     411              :                         m_vSCV[m_numSCV].vGloPos[2]=globalBary;
     412              :                         m_vSCV[m_numSCV].vLocPos[0]=m_rRefElem.corner(edgeCo[1]);
     413              :                         m_vSCV[m_numSCV].vLocPos[1]=localMidpoint;
     414              :                         m_vSCV[m_numSCV].vLocPos[2]=localBary;
     415            0 :                         m_vSCV[m_numSCV].numCorners = 3;
     416            0 :                         rTrialSpace.shapes(&(m_vSCV[m_numSCV].vShape[0]), m_vSCV[m_numSCV].local_ip());
     417            0 :                         rTrialSpace.grads(&(m_vSCV[m_numSCV].vLocalGrad[0]), m_vSCV[m_numSCV].local_ip());
     418              :                         // insert new scvf
     419            0 :                         m_vSCVF[m_numSCVF].From = m_numDofs;
     420            0 :                         m_vSCVF[m_numSCVF].To = m_numDofs+1;
     421              :                         m_vSCVF[m_numSCVF].vLocPos[0] = localMidpoint;
     422              :                         m_vSCVF[m_numSCVF].vLocPos[1] = localBary;
     423              :                         m_vSCVF[m_numSCVF].vGloPos[0] = globalMidpoint;
     424              :                         m_vSCVF[m_numSCVF].vGloPos[1] = globalBary;
     425            0 :                         m_vSCVF[m_numSCVF].numSH = rTrialSpace.num_sh();
     426            0 :                         for (int d=0;d<dim;d++) m_vSCVF[m_numSCVF].localIP[d] = 0.5*(localMidpoint[d] + localBary[d]);
     427            0 :                         for (int d=0;d<worldDim;d++) m_vSCVF[m_numSCVF].globalIP[d] = 0.5*(globalMidpoint[d] + globalBary[d]);
     428            0 :                         rTrialSpace.shapes(&(m_vSCVF[m_numSCVF].vShape[0]), m_vSCVF[m_numSCVF].local_ip());
     429            0 :                         rTrialSpace.grads(&(m_vSCVF[m_numSCVF].vLocalGrad[0]), m_vSCVF[m_numSCVF].local_ip());
     430            0 :                         ElementNormal<face_type0,worldDim>(m_vSCVF[m_numSCVF].Normal,m_vSCVF[m_numSCVF].vGloPos);
     431              :                         // insert new constrained dof object
     432            0 :                         m_vCD[m_numConstrainedDofs].i = side;
     433            0 :                         m_vCD[m_numConstrainedDofs].numConstrainingDofs = 2;
     434            0 :                         m_vCD[m_numConstrainedDofs].cDofInd[0] = m_numDofs;
     435            0 :                         m_vCD[m_numConstrainedDofs].cDofInd[1] = m_numDofs+1;
     436            0 :                         m_vCD[m_numConstrainedDofs].cDofWeights[0] = 0.5;
     437            0 :                         m_vCD[m_numConstrainedDofs].cDofWeights[1] = 0.5;
     438            0 :                         m_numSCV+=1+keepOffset;
     439            0 :                         m_numSCVF+=1;
     440            0 :                         m_numDofs+=2;
     441            0 :                         m_numConstrainedDofs+=1;
     442            0 :                         m_roid = ROID_UNKNOWN;
     443              :                 }
     444            0 :         } else {
     445              :                 // dim == 3
     446              :                 std::vector<Face*> vFaces;
     447            0 :                 CollectFacesSorted(vFaces, grid, pElem);
     448              :                 handledEdges.clear();
     449            0 :                 for(size_t face = 0; face < vFaces.size(); ++face){
     450            0 :                         ConstrainingFace* constrainingObj = dynamic_cast<ConstrainingFace*>(vFaces[face]);
     451            0 :                         if(constrainingObj == NULL) continue;
     452              :                         // found constraining face
     453              :                         MathVector<worldDim> globalMidpoint = m_vSCV[face].vGlobIP;
     454              :                         MathVector<dim> localMidpoint = m_vSCV[face].vLocIP;
     455            0 :                         number faceVol = m_vSCV[face].Vol;
     456              :                         MathVector<worldDim> faceNormal = m_vSCV[face].Normal;
     457              :                         // get face corners and edges
     458              :                         size_t faceCo[4];
     459              :                         size_t faceEdge[4];
     460              :                         // number of corners of face = number of edges
     461              :                         size_t numFaceCo = m_rRefElem.num(2,face,0);
     462            0 :                         for (size_t j=0;j<numFaceCo;j++) faceCo[j] = m_rRefElem.id(2,face,0,j);
     463            0 :                         for (size_t j=0;j<numFaceCo;j++) faceEdge[j] = m_rRefElem.id(2,face,1,j);
     464              :                         number volSum=0;
     465              :                         size_t keepOffset=0;
     466            0 :                         if (keepSCV) keepOffset=1;
     467              :                         // compute coordinates of each face and fill scv values
     468            0 :                         for (size_t i=0;i<numFaceCo;i++){
     469            0 :                                 size_t co = faceCo[i];
     470              :                                 size_t nOfEdges=0;
     471              :                                 size_t nbEdges[2];
     472              :                                 // find 2 edges in face belonging to node
     473            0 :                                 for (size_t j=0;j<m_rRefElem.num(0,co,1);j++){
     474            0 :                                         size_t candidate = m_rRefElem.id(0,co,1,j);
     475              :                                         bool found = false;
     476            0 :                                         for (size_t k=0;k<numFaceCo;k++){
     477            0 :                                                 if (faceEdge[k]==candidate){
     478              :                                                         found = true;
     479              :                                                         break;
     480              :                                                 }
     481              :                                         }
     482            0 :                                         if (found==true){
     483            0 :                                                 nbEdges[nOfEdges] = candidate;
     484            0 :                                                 nOfEdges++;
     485            0 :                                                 if (nOfEdges==2) break;
     486              :                                         }
     487              :                                 }
     488              :                                 // in triangular case switch edges if necessary for correct orientation
     489            0 :                                 if (numFaceCo==3){
     490            0 :                                         if (faceEdge[i]==nbEdges[1]){
     491            0 :                                                 nbEdges[1] = nbEdges[0];
     492            0 :                                                 nbEdges[0] = faceEdge[i];
     493              :                                         }
     494              :                                 }
     495              :                                 // keepSCV parameter specifies if scv "side" gets replaced by new one
     496            0 :                                 size_t ind = m_numSCV+i-1+keepOffset;
     497            0 :                                 if (i==0){
     498            0 :                                         if (keepSCV) ind=m_numSCV;
     499              :                                         else ind = face;
     500              :                                 }
     501              :                                 // others are inserted at the end
     502            0 :                                 m_vSCV[ind].vGloPos[0] = vCornerCoords[co];
     503              :                                 m_vSCV[ind].vLocPos[0] = m_rRefElem.corner(co);
     504            0 :                                 for (int d=0;d<worldDim;d++){
     505              :                                          // edge 0 midpoint
     506            0 :                                         m_vSCV[ind].vGloPos[1][d] = 0.5 * ( vCornerCoords[m_rRefElem.id(1,nbEdges[0],0,0)][d] + vCornerCoords[m_rRefElem.id(1,nbEdges[0],0,1)][d] );
     507            0 :                                         m_vSCV[ind].vLocPos[1][d] = 0.5 * ( m_rRefElem.corner(m_rRefElem.id(1,nbEdges[0],0,0))[d] + m_rRefElem.corner(m_rRefElem.id(1,nbEdges[0],0,1))[d] );
     508              :                                         // edge 1 midpoint
     509            0 :                                         m_vSCV[ind].vGloPos[numFaceCo-1][d] = 0.5 * ( vCornerCoords[m_rRefElem.id(1,nbEdges[1],0,0)][d] + vCornerCoords[m_rRefElem.id(1,nbEdges[1],0,1)][d] );
     510            0 :                                         m_vSCV[ind].vLocPos[numFaceCo-1][d] = 0.5 * ( m_rRefElem.corner(m_rRefElem.id(1,nbEdges[1],0,0))[d] + m_rRefElem.corner(m_rRefElem.id(1,nbEdges[1],0,1))[d] );
     511              :                                 }
     512            0 :                                 if (numFaceCo==4) m_vSCV[ind].vGloPos[2] = globalMidpoint;
     513              :                                 m_vSCV[ind].vGloPos[numFaceCo] = globalBary;
     514              :                                 m_vSCV[ind].vLocPos[numFaceCo] = localBary;
     515            0 :                                 m_vSCV[ind].numCorners = numFaceCo + 1;
     516            0 :                                 AveragePositions(m_vGlobUnkCoords[ind], m_vSCV[ind].vGloPos, m_vSCV[ind].numCorners-1);
     517            0 :                                 AveragePositions(m_vLocUnkCoords[ind], m_vSCV[ind].vLocPos, m_vSCV[ind].numCorners-1);
     518              :                                 m_vSCV[ind].vLocIP = m_vLocUnkCoords[ind];
     519              :                                 m_vSCV[ind].vGlobIP = m_vGlobUnkCoords[ind];
     520            0 :                                 m_vSCV[ind].numSH = rTrialSpace.num_sh();
     521            0 :                                 if (numFaceCo==3) m_vSCV[ind].Vol = ElementSize<scv_type0,worldDim>(m_vSCV[ind].vGloPos);
     522            0 :                                 else m_vSCV[ind].Vol = ElementSize<scv_type1,worldDim>(m_vSCV[ind].vGloPos);
     523            0 :                                 if (m_vSCV[ind].Vol<0) m_vSCV[ind].Vol *= -1;
     524            0 :                                 volSum+=m_vSCV[ind].Vol;
     525              :                                 m_vSCV[ind].Normal = faceNormal;
     526            0 :                                 m_vSCV[ind].Normal *= (number) m_vSCV[ind].Vol / faceVol;
     527            0 :                                 rTrialSpace.shapes(&(m_vSCV[ind].vShape[0]), m_vSCV[ind].local_ip());
     528            0 :                                 rTrialSpace.grads(&(m_vSCV[ind].vLocalGrad[0]), m_vSCV[ind].local_ip());
     529            0 :                                 m_vSCV[ind].nodeID = m_numDofs+i;
     530              :                         }
     531              :                         // compute inner scv in triangular case
     532            0 :                         if (numFaceCo==3){
     533            0 :                                 size_t ind = m_numSCV+2+keepOffset;
     534            0 :                                 m_vSCV[ind].Vol = faceVol - volSum;
     535            0 :                                 m_vSCV[ind].nodeID=m_numDofs+3;
     536              :                                 m_vSCV[ind].Normal = faceNormal;
     537            0 :                                 m_vSCV[ind].Normal *= (number) m_vSCV[ind].Vol / faceVol;
     538              :                                 m_vSCV[ind].vGlobIP = m_vSCV[face].vGloPos[1];
     539              :                                 m_vSCV[ind].vLocIP = m_vSCV[face].vLocPos[1];
     540            0 :                                 for (size_t j=0;j<2;j++){
     541            0 :                                         m_vSCV[ind].vGlobIP += m_vSCV[m_numSCV+j].vGloPos[1];
     542              :                                         m_vSCV[ind].vLocIP += m_vSCV[m_numSCV+j].vLocPos[1];
     543              :                                 }
     544              :                                 m_vSCV[ind].vGlobIP *= (number)1.0/3.0;
     545              :                                 m_vSCV[ind].vLocIP *= (number)1.0/3.0;
     546              :                                 m_vGlobUnkCoords[ind] = m_vSCV[ind].vGlobIP;
     547              :                                 m_vLocUnkCoords[ind] = m_vSCV[ind].vLocIP;
     548            0 :                                 m_vSCV[ind].numCorners = numFaceCo + 1;
     549            0 :                                 m_vSCV[ind].numSH = rTrialSpace.num_sh();
     550            0 :                                 rTrialSpace.shapes(&(m_vSCV[ind].vShape[0]), m_vSCV[ind].local_ip());
     551            0 :                                 rTrialSpace.grads(&(m_vSCV[ind].vLocalGrad[0]), m_vSCV[ind].local_ip());
     552              :                         }
     553              :                         // copy scvfs into constrained scvfs
     554            0 :                         if (keepSCVF){
     555            0 :                                 for (size_t i=0;i<numFaceCo;i++){
     556            0 :                                         size_t edge = faceEdge[i];
     557            0 :                                         m_vConstrainedSCVF[m_numConstrainedSCVF+i] = m_vSCVF[edge];
     558            0 :                                         if (m_vConstrainedSCVF[m_numConstrainedSCVF+i].To==face){
     559            0 :                                                 m_vConstrainedSCVF[m_numConstrainedSCVF+i].From=face;
     560              :                                                 m_vConstrainedSCVF[m_numConstrainedSCVF+i].Normal*=-1;
     561              :                                         }
     562              :                                 }
     563            0 :                                 m_numConstrainedSCVF += numFaceCo;
     564              :                         }
     565              :                         // insert new scvfs, first the ones associated to edges of face
     566            0 :                         for (size_t i=0;i<numFaceCo;i++){
     567            0 :                                 size_t edge = faceEdge[i];
     568            0 :                                 size_t from = m_vSCVF[edge].From;
     569            0 :                                 size_t to   = m_vSCVF[edge].To;
     570              :                                 MathVector<worldDim> normal = m_vSCVF[edge].Normal;
     571              :                                 normal*=0.5;
     572              :                                 size_t edgeCo[2];
     573              :                                 size_t scvID[2];
     574            0 :                                 for (size_t j=0;j<2;j++){
     575            0 :                                         edgeCo[j] = m_rRefElem.id(1,edge,0,j);
     576              :                                         // find corresponding face vertex (= corresponding scv index)
     577            0 :                                         for (size_t k=0;k<numFaceCo;k++){
     578            0 :                                                 if (faceCo[k]==edgeCo[j]){
     579            0 :                                                         scvID[j] = m_numDofs+k;
     580            0 :                                                         break;
     581              :                                                 }
     582              :                                         }
     583              :                                 }
     584              :                                 // look if edge has already been handled
     585            0 :                                 if (m_numConstrainedDofs>0){
     586              :                                         bool found=false;
     587            0 :                                         for (size_t j=0;j<handledEdges.size();j++){
     588            0 :                                                 if (handledEdges[j].index==edge){
     589              :                                                         HandledEdge& hE=handledEdges[j];
     590              :                                                         found=true;
     591              :                                                         // set new from/to values
     592            0 :                                                         for (size_t k=0;k<2;k++){
     593            0 :                                                                 if (hE.from){
     594            0 :                                                                         m_vSCVF[hE.scvfIndex+k].To=scvID[k];    
     595              :                                                                 } else {
     596            0 :                                                                         m_vSCVF[hE.scvfIndex+k].From=scvID[k];
     597              :                                                                 }
     598              :                                                         }
     599              :                                                         // mark edge so associated scvf is not overwritten
     600            0 :                                                         faceEdge[i]=deleted;
     601              :                                                         break;
     602              :                                                 }
     603              :                                         }
     604            0 :                                         if (found==true) continue;
     605              :                                 }
     606              :                                 HandledEdge hEdge;
     607            0 :                                 hEdge.index=edge;
     608            0 :                                 hEdge.scvfIndex=m_numSCVF;
     609              :                                 MathVector<worldDim> edgeMidGlob;
     610              :                                 MathVector<dim> edgeMidLoc;
     611            0 :                                 for (int d=0;d<worldDim;d++){
     612            0 :                                         edgeMidGlob[d] = 0.5 * (vCornerCoords[edgeCo[0]][d]  + vCornerCoords[edgeCo[1]][d]);
     613            0 :                                         edgeMidLoc[d] = 0.5 * (m_rRefElem.corner(edgeCo[0])[d] +  m_rRefElem.corner(edgeCo[1])[d]);
     614              :                                 }
     615            0 :                                 for (size_t j=0;j<2;j++){
     616            0 :                                         hEdge.associatedSCV[j] = scvID[j];
     617            0 :                                         if (from==face){
     618            0 :                                                 m_vSCVF[m_numSCVF].From = scvID[j];
     619            0 :                                                 m_vSCVF[m_numSCVF].To   = to;
     620            0 :                                                 hEdge.from=true;
     621              :                                         } else {
     622            0 :                                                 m_vSCVF[m_numSCVF].From = from;
     623            0 :                                                 m_vSCVF[m_numSCVF].To   = scvID[j];
     624            0 :                                                 hEdge.from=false;
     625              :                                         }
     626            0 :                                         m_vSCVF[m_numSCVF].Normal = normal;
     627            0 :                                         m_vSCVF[m_numSCVF].vGloPos[0] = vCornerCoords[edgeCo[j]];
     628              :                                         m_vSCVF[m_numSCVF].vLocPos[0] = m_rRefElem.corner(edgeCo[j]);
     629              :                                         m_vSCVF[m_numSCVF].vGloPos[1] = edgeMidGlob;
     630              :                                         m_vSCVF[m_numSCVF].vLocPos[1] = edgeMidLoc;
     631              :                                         m_vSCVF[m_numSCVF].vGloPos[2] = globalBary;
     632              :                                         m_vSCVF[m_numSCVF].vLocPos[2] = localBary;
     633            0 :                                         m_vSCVF[m_numSCVF].numSH = rTrialSpace.num_sh();
     634            0 :                                         AveragePositions(m_vSCVF[m_numSCVF].localIP, m_vSCVF[m_numSCVF].vLocPos, m_vSCVF[m_numSCVF].numCo);
     635            0 :                                         AveragePositions(m_vSCVF[m_numSCVF].globalIP, m_vSCVF[m_numSCVF].vGloPos, m_vSCVF[m_numSCVF].numCo);
     636            0 :                                         rTrialSpace.shapes(&(m_vSCVF[m_numSCVF].vShape[0]), m_vSCVF[m_numSCVF].local_ip());
     637            0 :                                         rTrialSpace.grads(&(m_vSCVF[m_numSCVF].vLocalGrad[0]), m_vSCVF[m_numSCVF].local_ip());
     638            0 :                                         m_numSCVF++;
     639              :                                 }
     640            0 :                                 handledEdges.push_back(hEdge);
     641              :                         }
     642              :                         // scvfs inside the face
     643              :                         // insert remaining inner scvfs into positions of edge associated scvs
     644            0 :                         for (size_t j=0;j<numFaceCo;j++){
     645              :                                 // replaces edge associated scvf
     646            0 :                                 size_t ii = faceEdge[j];
     647            0 :                                 if (ii==deleted){ 
     648            0 :                                         ii = m_numSCVF;
     649            0 :                                         m_numSCVF++;
     650              :                                 }
     651            0 :                                 if (numFaceCo==3){
     652              :                                         // compute inner scvfs in triangular case
     653            0 :                                         m_vSCVF[ii].From = m_numDofs+3;
     654            0 :                                         m_vSCVF[ii].To = m_numDofs+j;
     655              :                                         size_t ind = face;
     656            0 :                                         if (j>0) ind = m_numSCV+j-1;
     657              :                                         m_vSCVF[ii].vLocPos[0] = m_vSCV[ind].vLocPos[1];
     658              :                                         m_vSCVF[ii].vLocPos[1] = m_vSCV[ind].vLocPos[2];
     659              :                                         m_vSCVF[ii].vGloPos[0] = m_vSCV[ind].vGloPos[1];
     660              :                                         m_vSCVF[ii].vGloPos[1] = m_vSCV[ind].vGloPos[2];
     661              :                                 }else{
     662              :                                         // compute inner scvfs in quadrilateral case
     663            0 :                                         m_vSCVF[ii].To = m_numDofs+j;
     664            0 :                                         m_vSCVF[ii].From = m_numDofs + ((j+1) % 4);
     665            0 :                                         for (int d=0;d<worldDim;d++){
     666            0 :                                                 m_vSCVF[ii].vLocPos[0][d] = 0.5*( m_rRefElem.corner(faceCo[j])[d] + m_rRefElem.corner(faceCo[(j+1) % 4])[d] );
     667            0 :                                                 m_vSCVF[ii].vGloPos[0][d] = 0.5*( vCornerCoords[faceCo[j]][d] + vCornerCoords[faceCo[(j+1) % 4]][d] );
     668              :                                         }
     669              :                                         m_vSCVF[ii].vLocPos[1] = localMidpoint;
     670              :                                         m_vSCVF[ii].vGloPos[1] = globalMidpoint;
     671              :                                 }
     672              :                                 m_vSCVF[ii].vLocPos[2] = localBary;
     673              :                                 m_vSCVF[ii].vGloPos[2] = globalBary;    
     674            0 :                                 m_vSCVF[ii].numSH = rTrialSpace.num_sh();
     675            0 :                                 ElementNormal<face_type0,worldDim>(m_vSCVF[ii].Normal,m_vSCVF[ii].vGloPos);
     676            0 :                                 AveragePositions(m_vSCVF[ii].globalIP,m_vSCVF[ii].vGloPos,3);
     677            0 :                                 AveragePositions(m_vSCVF[ii].localIP,m_vSCVF[ii].vLocPos,3);
     678            0 :                                 rTrialSpace.shapes(&(m_vSCVF[ii].vShape[0]), m_vSCVF[ii].local_ip());
     679            0 :                                 rTrialSpace.grads(&(m_vSCVF[ii].vLocalGrad[0]), m_vSCVF[ii].local_ip());
     680              :                         }
     681              :                         // insert new constrained dof object
     682            0 :                         m_vCD[m_numConstrainedDofs].i = face;
     683            0 :                         m_vCD[m_numConstrainedDofs].numConstrainingDofs = 4;
     684            0 :                         for (size_t i=0;i<4;i++){
     685            0 :                                 m_vCD[m_numConstrainedDofs].cDofInd[i] = m_numDofs+i;
     686              :                                 size_t ind=face;
     687            0 :                                 if (i>0) ind = m_numSCV+i-1;
     688            0 :                                 m_vCD[m_numConstrainedDofs].cDofWeights[i] = (number)m_vSCV[ind].Vol / faceVol;
     689              :                         }
     690            0 :                         m_numSCV+=3+keepOffset;
     691            0 :                         m_numDofs+=4;
     692            0 :                         m_numConstrainedDofs+=1;
     693            0 :                         m_roid = ROID_UNKNOWN;
     694              :                 }
     695            0 :         }// end of hanging node check
     696              : 
     697              :         //\todo compute with one virt. call
     698              : //      compute jacobian for linear mapping
     699            0 :         if(rMapping.is_linear())
     700              :         {
     701              :                 MathMatrix<worldDim,dim> JtInv;
     702            0 :                 rMapping.jacobian_transposed_inverse(JtInv, m_vSCVF[0].local_ip());
     703            0 :                 const number detJ = rMapping.sqrt_gram_det(m_vSCVF[0].local_ip());
     704              : 
     705            0 :                 for(size_t i = 0; i < num_scvf(); ++i)
     706              :                 {
     707              :                         m_vSCVF[i].JtInv = JtInv;
     708            0 :                         m_vSCVF[i].detj = detJ;
     709              :                 }
     710              : 
     711            0 :                 for(size_t i = 0; i < num_scv(); ++i)
     712              :                 {
     713              :                         m_vSCV[i].JtInv = JtInv;
     714            0 :                         m_vSCV[i].detj = detJ;
     715              :                 }
     716              :         }
     717              : //      else compute jacobian for each integration point
     718              :         else
     719              :         {
     720            0 :                 for(size_t i = 0; i < num_scvf(); ++i)
     721              :                 {
     722            0 :                         rMapping.jacobian_transposed_inverse(m_vSCVF[i].JtInv, m_vSCVF[i].local_ip());
     723            0 :                         m_vSCVF[i].detj = rMapping.sqrt_gram_det(m_vSCVF[i].local_ip());
     724              :                 }
     725            0 :                 for(size_t i = 0; i < num_scv(); ++i)
     726              :                 {
     727            0 :                         rMapping.jacobian_transposed_inverse(m_vSCV[i].JtInv, m_vSCV[i].local_ip());
     728            0 :                         m_vSCV[i].detj = rMapping.sqrt_gram_det(m_vSCV[i].local_ip());
     729              :                 }
     730              :         }
     731              : 
     732              : //      compute global gradients
     733            0 :         for(size_t i = 0; i < num_scvf(); ++i)
     734            0 :                 for(size_t sh = 0; sh < scvf(i).num_sh(); ++sh)
     735              :                         MatVecMult(m_vSCVF[i].vGlobalGrad[sh], m_vSCVF[i].JtInv, m_vSCVF[i].vLocalGrad[sh]);
     736              : 
     737            0 :         for(size_t i = 0; i < num_scv(); ++i)
     738            0 :                 for(size_t sh = 0; sh < scv(i).num_sh(); ++sh)
     739              :                         MatVecMult(m_vSCV[i].vGlobalGrad[sh], m_vSCV[i].JtInv, m_vSCV[i].vLocalGrad[sh]);
     740              : 
     741              : //      copy ip points in list (SCVF)
     742            0 :         for(size_t i = 0; i < num_scvf(); ++i)
     743              :                 m_vGlobSCVF_IP[i] = scvf(i).global_ip();
     744              : 
     745              : //      if no boundary subsets required, return
     746            0 :         if(num_boundary_subsets() == 0 || ish == NULL) return;
     747            0 :         else update_boundary_faces(pElem, vCornerCoords, ish);
     748              : }
     749              : 
     750              : 
     751              : /// update geometric data for given element (no shapes)
     752              : template <int TDim, int TWorldDim>
     753            0 : void DimCRFVGeometry<TDim, TWorldDim>::
     754              : update_geometric_data(GridObject* pElem, const MathVector<worldDim>* vCornerCoords, const ISubsetHandler* ish)
     755              : {
     756              : //      If already update for this element, do nothing
     757            0 :         if(m_pElem == pElem) return; else m_pElem = pElem;
     758              : 
     759              : //      refresh local data, if different roid given
     760            0 :         if(m_roid != pElem->reference_object_id())
     761              :         {
     762              :         //      remember new roid
     763            0 :                 m_roid = (ReferenceObjectID) pElem->reference_object_id();
     764              : 
     765              :         //      update local data
     766            0 :                 update_local_data();
     767              :         }
     768              : 
     769              : //      get reference element
     770              :         try{
     771              :         const DimReferenceElement<dim>& rRefElem
     772            0 :                 = ReferenceElementProvider::get<dim>(m_roid);
     773              : 
     774              :         //  compute barycenter coordinates
     775              :         globalBary = vCornerCoords[0];
     776            0 :         for (size_t j=1;j<rRefElem.num(0);j++){
     777            0 :            globalBary+=vCornerCoords[j];
     778              :         }
     779            0 :         globalBary*=1./(number)rRefElem.num(0);
     780              : 
     781              : //      compute global informations for scvf
     782            0 :         for(size_t i = 0; i < num_scvf(); ++i)
     783              :         {
     784            0 :                 for (size_t j=0;j<m_vSCVF[i].numCo-1;j++){
     785            0 :                         m_vSCVF[i].vGloPos[j]=vCornerCoords[rRefElem.id(dim-2,i,0,j)];
     786              :                 }
     787              :                 m_vSCVF[i].vGloPos[m_vSCVF[i].numCo-1]=globalBary;
     788            0 :                 AveragePositions(m_vSCVF[i].globalIP, m_vSCVF[i].vGloPos, m_vSCVF[i].numCo);
     789            0 :                 ElementNormal<face_type0,worldDim>(m_vSCVF[i].Normal,m_vSCVF[i].vGloPos);// face_type0 identical to scvf type
     790              :         }
     791              : 
     792              : //      compute size of scv
     793            0 :         for(size_t i = 0; i < num_scv(); ++i)
     794              :         {
     795              :                 // side nodes in reverse order to fulfill standard element order
     796            0 :                 for (int j=0;j<m_vSCV[i].numCorners-1;j++){
     797            0 :                         m_vSCV[i].vGloPos[m_vSCV[i].numCorners-2-j]=vCornerCoords[rRefElem.id(dim-1,i,0,j)];
     798              :                 }
     799            0 :                 AveragePositions(m_vGlobUnkCoords[i], m_vSCV[i].vGloPos, m_vSCV[i].numCorners-1);
     800              :                 m_vSCV[i].vGlobIP = m_vGlobUnkCoords[i];
     801              :                 
     802              :                 m_vSCV[i].vGloPos[m_vSCV[i].numCorners-1]=globalBary;
     803              :                 //      compute volume of scv and normal to associated element face
     804              :                 //CRSCVSizeAndNormal<dim>(m_vSCV[i].Vol,m_vSCV[i].Normal,m_vSCV[i].vGloPos,m_vSCV[i].numCorners);
     805            0 :                 if (m_vSCV[i].numCorners-1==dim){
     806            0 :                      m_vSCV[i].Vol = ElementSize<scv_type0,worldDim>(m_vSCV[i].vGloPos);
     807            0 :                      ElementNormal<face_type0, worldDim>(m_vSCV[i].Normal, m_vSCV[i].vGloPos);
     808              :                 } else { // m_vSCV[i].numCorners-2==dim , only possible in 3d (pyramid)
     809            0 :                      m_vSCV[i].Vol = ElementSize<scv_type1,worldDim>(m_vSCV[i].vGloPos);
     810            0 :                      ElementNormal<face_type1,worldDim>(m_vSCV[i].Normal, m_vSCV[i].vGloPos);
     811              :                 };
     812              :                 // nodes are in reverse order therefore reverse sign to get outward normal
     813              :                 m_vSCV[i].Normal*=-1;
     814              :         }
     815              :         
     816              :         }
     817            0 :         UG_CATCH_THROW("DimCRFVGeometry: geometric update failed.");
     818              : }
     819              : 
     820              : 
     821              : template <int TDim, int TWorldDim>
     822            0 : void DimCRFVGeometry<TDim, TWorldDim>::
     823              : update_boundary_faces(GridObject* pElem, const MathVector<worldDim>* vCornerCoords, const ISubsetHandler* ish)
     824              : {
     825              : //      get grid
     826            0 :         Grid& grid = *(ish->grid());
     827              : 
     828              : //      vector of subset indices of side
     829              :         std::vector<int> vSubsetIndex;
     830              : 
     831              : //      get subset indices for sides (i.e. edge in 2d, faces in 3d)
     832              :         if(dim == 1) {
     833              :                 std::vector<Vertex*> vVertex;
     834              :                 CollectVertices(vVertex, grid, pElem);
     835              :                 vSubsetIndex.resize(vVertex.size());
     836              :                 for(size_t i = 0; i < vVertex.size(); ++i)
     837              :                         vSubsetIndex[i] = ish->get_subset_index(vVertex[i]);
     838              :         }
     839              :         if(dim == 2) {
     840              :                 std::vector<Edge*> vEdges;
     841            0 :                 CollectEdgesSorted(vEdges, grid, pElem);
     842            0 :                 vSubsetIndex.resize(vEdges.size());
     843            0 :                 for(size_t i = 0; i < vEdges.size(); ++i)
     844            0 :                         vSubsetIndex[i] = ish->get_subset_index(vEdges[i]);
     845            0 :         }
     846              :         if(dim == 3) {
     847              :                 std::vector<Face*> vFaces;
     848            0 :                 CollectFacesSorted(vFaces, grid, pElem);
     849            0 :                 vSubsetIndex.resize(vFaces.size());
     850            0 :                 for(size_t i = 0; i < vFaces.size(); ++i)
     851            0 :                         vSubsetIndex[i] = ish->get_subset_index(vFaces[i]);
     852            0 :         }
     853              : 
     854              :         try{
     855              : //      const DimReferenceElement<dim>& rRefElem
     856              :         //      = ReferenceElementProvider::get<dim>(m_roid);
     857              : 
     858            0 :         DimReferenceMapping<dim, worldDim>& rMapping = ReferenceMappingProvider::get<dim, worldDim>(m_roid);
     859            0 :         rMapping.update(vCornerCoords);
     860              : 
     861              :         const LocalShapeFunctionSet<dim>& TrialSpace =
     862            0 :                 LocalFiniteElementProvider::get<dim>(m_roid, LFEID(LFEID::CROUZEIX_RAVIART, dim, 1));
     863              : 
     864              : //      loop requested subset
     865              :         typename std::map<int, std::vector<BF> >::iterator it;
     866            0 :         for (it=m_mapVectorBF.begin() ; it != m_mapVectorBF.end(); ++it)
     867              :         {
     868              :         //      get subset index
     869            0 :                 const int bndIndex = (*it).first;
     870              : 
     871              :         //      get vector of BF for element
     872            0 :                 std::vector<BF>& vBF = (*it).second;
     873              : 
     874              :         //      clear vector
     875              :                 vBF.clear();
     876              : 
     877              :         //      current number of bf
     878              :                 size_t curr_bf = 0;
     879              : 
     880              :         //      loop sides of element
     881            0 :                 for(size_t side = 0; side < vSubsetIndex.size(); ++side)
     882              :                 {
     883              :                 //      skip non boundary sides
     884            0 :                         if(vSubsetIndex[side] != bndIndex) continue;
     885              : 
     886              :                 //      number of corners of side
     887              :                         // const int coOfSide = rRefElem.num(dim-1, side, 0); todo use somewhere?
     888              : 
     889              :                 //      resize vector
     890            0 :                         vBF.resize(curr_bf + 1);
     891              : 
     892              :                 //  fill BF with data from associated SCV
     893              :                         BF& bf = vBF[curr_bf];
     894            0 :                         bf.nodeID =     m_vSCV[side].nodeID;
     895              : 
     896              :                         bf.localIP =  m_vSCV[side].vLocIP;
     897              :                         bf.globalIP = m_vSCV[side].vGlobIP;
     898              : 
     899              :                         bf.Normal = m_vSCV[side].Normal;
     900              :                         //      compute volume
     901            0 :                         bf.Vol = VecTwoNorm(bf.Normal);
     902              : 
     903            0 :                         bf.numCo = m_vSCV[side].numCorners-1;
     904              : 
     905              :                         //      compute shapes and grads
     906            0 :                         bf.numSH = TrialSpace.num_sh();
     907            0 :                         TrialSpace.shapes(&(bf.vShape[0]), bf.localIP);
     908            0 :                         TrialSpace.grads(&(bf.vLocalGrad[0]), bf.localIP);
     909              : 
     910              :                         //      get reference mapping
     911            0 :                         rMapping.jacobian_transposed_inverse(bf.JtInv, bf.localIP);
     912            0 :                         bf.detj = rMapping.sqrt_gram_det(bf.localIP);
     913              : 
     914              :                         //      compute global gradients
     915            0 :                         for(size_t sh = 0 ; sh < bf.num_sh(); ++sh)
     916              :                                 MatVecMult(bf.vGlobalGrad[sh], bf.JtInv, bf.vLocalGrad[sh]);
     917              : 
     918              :                         //      increase curr_bf
     919              :                         ++curr_bf;
     920              :                 }
     921              :         }
     922              : 
     923              :         }
     924            0 :         UG_CATCH_THROW("DimCRFVGeometry: update failed.");
     925            0 : }
     926              : 
     927              : ////////////////////////////////////////////////////////////////////////////////
     928              : ////////////////////////////////////////////////////////////////////////////////
     929              : //// Methods for CRFVGeometry class
     930              : ////////////////////////////////////////////////////////////////////////////////
     931              : ////////////////////////////////////////////////////////////////////////////////
     932              : 
     933              : template <   typename TElem, int TWorldDim>
     934            0 : CRFVGeometry<TElem, TWorldDim>::
     935              : CRFVGeometry()
     936            0 :         : m_pElem(NULL), m_rRefElem(Provider<ref_elem_type>::get()),
     937            0 :           m_rTrialSpace(Provider<local_shape_fct_set_type>::get())
     938              : {
     939            0 :         update_local_data();
     940            0 : }
     941              : 
     942              : template <   typename TElem, int TWorldDim>
     943            0 : void CRFVGeometry<TElem, TWorldDim>::
     944              : update_local_data()
     945              : {
     946              : //  compute barycenter coordinates
     947            0 :         localBary = m_rRefElem.corner(0);
     948            0 :         for (size_t j=1;j<m_rRefElem.num(0);j++){
     949              :                 localBary+=m_rRefElem.corner(j);
     950              :         }
     951            0 :         localBary*=1./(number)m_rRefElem.num(0);
     952              : 
     953              : //      set up local informations for SubControlVolumeFaces (scvf)
     954              : //      each scvf is associated to one vertex (2d) / edge (3d) of the element
     955            0 :         for(size_t i = 0; i < numSCVF; ++i)
     956              :         {
     957              :         //      this scvf separates the given edges/faces
     958            0 :                 m_vSCVF[i].From = m_rRefElem.id(dim-2, i, dim-1, 0);// todo handle dim==1
     959            0 :                 m_vSCVF[i].To = m_rRefElem.id(dim-2, i, dim-1, 1);
     960              : 
     961            0 :                 for (size_t j=0;j<m_vSCVF[i].numCo-1;j++){
     962            0 :                         m_vSCVF[i].vLocPos[j]=m_rRefElem.corner(m_rRefElem.id(dim-2,i,0,j));
     963              :                 }
     964              : 
     965              :                 m_vSCVF[i].vLocPos[m_vSCVF[i].numCo-1]=localBary;
     966              : 
     967            0 :                 AveragePositions(m_vSCVF[i].localIP, m_vSCVF[i].vLocPos, m_vSCVF[i].numCo);
     968              :         }
     969              : 
     970              : //      set up local informations for SubControlVolumes (scv)
     971              : //      each scv is associated to one edge (2d) / face (3d) of the element
     972            0 :         for(size_t i = 0; i < numSCV; ++i)
     973              :         {
     974              :         //      store associated node
     975            0 :                 m_vSCV[i].nodeID = i;
     976              : 
     977            0 :                 m_vSCV[i].numCorners = m_rRefElem.num(dim-1,i,0)+1;
     978            0 :                 for (int j=0;j<m_vSCV[i].numCorners-1;j++){
     979            0 :                         m_vSCV[i].vLocPos[m_vSCV[i].numCorners-2-j]=m_rRefElem.corner(m_rRefElem.id(dim-1,i,0,j));
     980              :                 }
     981            0 :                 AveragePositions(m_vLocUnkCoords[i], m_vSCV[i].vLocPos, m_vSCV[i].numCorners-1);
     982              :                 m_vSCV[i].vLocIP=m_vLocUnkCoords[i];
     983              : 
     984              :                 m_vSCV[i].vLocPos[m_vSCV[i].numCorners-1]=localBary;
     985              :         }
     986              : 
     987              :         /////////////////////////
     988              :         // Shapes and Derivatives
     989              :         /////////////////////////
     990              : 
     991              : //      compute Shapes and Derivatives
     992            0 :         for(size_t i = 0; i < numSCVF; ++i)
     993              :         {
     994            0 :                 m_rTrialSpace.shapes(&(m_vSCVF[i].vShape[0]), m_vSCVF[i].local_ip());
     995            0 :                 m_rTrialSpace.grads(&(m_vSCVF[i].vLocalGrad[0]), m_vSCVF[i].local_ip());
     996              :         }
     997              : 
     998            0 :         for(size_t i = 0; i < numSCV; ++i)
     999              :         {
    1000            0 :                 m_rTrialSpace.shapes(&(m_vSCV[i].vShape[0]), m_vSCV[i].local_ip());
    1001            0 :                 m_rTrialSpace.grads(&(m_vSCV[i].vLocalGrad[0]), m_vSCV[i].local_ip());
    1002              :         }
    1003              : 
    1004              : //      copy ip positions in a list for Sub Control Volumes Faces (SCVF)
    1005            0 :         for(size_t i = 0; i < num_scvf(); ++i)
    1006              :                 m_vLocSCVF_IP[i] = scvf(i).local_ip();
    1007            0 : }
    1008              : 
    1009              : 
    1010              : /// update data for given element
    1011              : template <   typename TElem, int TWorldDim>
    1012            0 : void CRFVGeometry<TElem, TWorldDim>::
    1013              : update(GridObject* elem, const MathVector<worldDim>* vCornerCoords, const ISubsetHandler* ish)
    1014              : {
    1015              :         UG_ASSERT(dynamic_cast<TElem*>(elem) != NULL, "Wrong element type.");
    1016              :         TElem* pElem = static_cast<TElem*>(elem);
    1017              : 
    1018              : //      If already update for this element, do nothing
    1019            0 :         if(m_pElem == pElem) return; else m_pElem = pElem;
    1020              : 
    1021              :         //  compute barycenter coordinates
    1022              :         globalBary = vCornerCoords[0];
    1023              :         m_vCo[0] = vCornerCoords[0];
    1024            0 :         for (size_t j=1;j<m_rRefElem.num(0);j++){
    1025            0 :            globalBary+=vCornerCoords[j];
    1026              :            m_vCo[j] = vCornerCoords[j];
    1027              :         }
    1028            0 :         globalBary*=1./(number)m_rRefElem.num(0);
    1029              : 
    1030              : //      compute global informations for scvf
    1031            0 :         for(size_t i = 0; i < num_scvf(); ++i)
    1032              :         {
    1033            0 :                 for (size_t j=0;j<m_vSCVF[i].numCo-1;j++){
    1034            0 :                         m_vSCVF[i].vGloPos[j]=vCornerCoords[m_rRefElem.id(dim-2,i,0,j)];
    1035              :                 }
    1036              :                 m_vSCVF[i].vGloPos[m_vSCVF[i].numCo-1]=globalBary;
    1037            0 :                 AveragePositions(m_vSCVF[i].globalIP, m_vSCVF[i].vGloPos, m_vSCVF[i].numCo);
    1038            0 :                 ElementNormal<face_type0,worldDim>(m_vSCVF[i].Normal,m_vSCVF[i].vGloPos);// face_type0 identical to scvf type
    1039              :         }
    1040              : 
    1041              : //      compute size of scv
    1042            0 :         for(size_t i = 0; i < num_scv(); ++i)
    1043              :         {
    1044              :                 // side nodes in reverse order to fulfill standard element order
    1045            0 :                 for (int j=0;j<m_vSCV[i].numCorners-1;j++){
    1046            0 :                         m_vSCV[i].vGloPos[m_vSCV[i].numCorners-2-j]=vCornerCoords[m_rRefElem.id(dim-1,i,0,j)];
    1047              :                 }
    1048            0 :                 AveragePositions(m_vGlobUnkCoords[i], m_vSCV[i].vGloPos, m_vSCV[i].numCorners-1);
    1049              :                 m_vSCV[i].vGlobIP = m_vGlobUnkCoords[i];
    1050              : 
    1051              :                 m_vSCV[i].vGloPos[m_vSCV[i].numCorners-1]=globalBary;
    1052              :                 //      compute volume of scv and normal to associated element face
    1053              :                 //CRSCVSizeAndNormal<dim>(m_vSCV[i].Vol,m_vSCV[i].Normal,m_vSCV[i].vGloPos,m_vSCV[i].numCorners);
    1054            0 :                 if (m_vSCV[i].numCorners-1==dim){
    1055            0 :                      m_vSCV[i].Vol = ElementSize<scv_type0,worldDim>(m_vSCV[i].vGloPos);
    1056            0 :                      ElementNormal<face_type0, worldDim>(m_vSCV[i].Normal, m_vSCV[i].vGloPos);
    1057              :                 } else { // m_vSCV[i].numCorners-2==dim , only possible in 3d (pyramid)
    1058            0 :                      m_vSCV[i].Vol = ElementSize<scv_type1,worldDim>(m_vSCV[i].vGloPos);
    1059            0 :                      ElementNormal<face_type1, worldDim>(m_vSCV[i].Normal, m_vSCV[i].vGloPos);
    1060              :                 };
    1061              :                 // nodes are in reverse order therefore reverse sign to get outward normal
    1062              :                 m_vSCV[i].Normal*=-1;
    1063              :         }
    1064              : 
    1065              : //      Shapes and Derivatives
    1066            0 :         m_mapping.update(vCornerCoords);
    1067              : 
    1068              : //      compute jacobian for linear mapping
    1069              :         if(ReferenceMapping<ref_elem_type, worldDim>::isLinear)
    1070              :         {
    1071              :                 MathMatrix<worldDim,dim> JtInv;
    1072            0 :                 m_mapping.jacobian_transposed_inverse(JtInv, m_vSCVF[0].local_ip());
    1073            0 :                 const number detJ = m_mapping.sqrt_gram_det(m_vSCVF[0].local_ip());
    1074              : 
    1075            0 :                 for(size_t i = 0; i < num_scvf(); ++i)
    1076              :                 {
    1077              :                         m_vSCVF[i].JtInv = JtInv;
    1078            0 :                         m_vSCVF[i].detj = detJ;
    1079              :                 }
    1080              : 
    1081            0 :                 for(size_t i = 0; i < num_scv(); ++i)
    1082              :                 {
    1083              :                         m_vSCV[i].JtInv = JtInv;
    1084            0 :                         m_vSCV[i].detj = detJ;
    1085              :                 }
    1086              :         }
    1087              : //      else compute jacobian for each integration point
    1088              :         else
    1089              :         {
    1090            0 :                 for(size_t i = 0; i < num_scvf(); ++i)
    1091              :                 {
    1092            0 :                         m_mapping.jacobian_transposed_inverse(m_vSCVF[i].JtInv, m_vSCVF[i].local_ip());
    1093            0 :                         m_vSCVF[i].detj = m_mapping.sqrt_gram_det(m_vSCVF[i].local_ip());
    1094              :                 }
    1095            0 :                 for(size_t i = 0; i < num_scv(); ++i)
    1096              :                 {
    1097            0 :                         m_mapping.jacobian_transposed_inverse(m_vSCV[i].JtInv, m_vSCV[i].local_ip());
    1098            0 :                         m_vSCV[i].detj = m_mapping.sqrt_gram_det(m_vSCV[i].local_ip());
    1099              :                 }
    1100              :         }
    1101              : 
    1102              : //      compute global gradients
    1103            0 :         for(size_t i = 0; i < num_scvf(); ++i)
    1104            0 :                 for(size_t sh = 0; sh < scvf(i).num_sh(); ++sh)
    1105              :                         MatVecMult(m_vSCVF[i].vGlobalGrad[sh], m_vSCVF[i].JtInv, m_vSCVF[i].vLocalGrad[sh]);
    1106              : 
    1107            0 :         for(size_t i = 0; i < num_scv(); ++i)
    1108            0 :                 for(size_t sh = 0; sh < scv(i).num_sh(); ++sh)
    1109              :                         MatVecMult(m_vSCV[i].vGlobalGrad[sh], m_vSCV[i].JtInv, m_vSCV[i].vLocalGrad[sh]);
    1110              : 
    1111              : //      copy ip points in list (SCVF)
    1112            0 :         for(size_t i = 0; i < num_scvf(); ++i)
    1113              :                 m_vGlobSCVF_IP[i] = scvf(i).global_ip();
    1114              : 
    1115              : //      if no boundary subsets required, return
    1116            0 :         if(num_boundary_subsets() == 0 || ish == NULL) return;
    1117            0 :         else update_boundary_faces(pElem, vCornerCoords, ish);
    1118              : }
    1119              : 
    1120              : template <   typename TElem, int TWorldDim>
    1121            0 : void CRFVGeometry<TElem, TWorldDim>::
    1122              : update_boundary_faces(GridObject* pElem, const MathVector<worldDim>* vCornerCoords, const ISubsetHandler* ish)
    1123              : {
    1124              : //      get grid
    1125            0 :         Grid& grid = *(ish->grid());
    1126              : 
    1127              : //      vector of subset indices of side
    1128              :         std::vector<int> vSubsetIndex;
    1129              : 
    1130              : //      get subset indices for sides (i.e. edge in 2d, faces in 3d)
    1131              :         if(dim == 1) {
    1132              :                 std::vector<Vertex*> vVertex;
    1133              :                 CollectVertices(vVertex, grid, pElem);
    1134              :                 vSubsetIndex.resize(vVertex.size());
    1135              :                 for(size_t i = 0; i < vVertex.size(); ++i)
    1136              :                         vSubsetIndex[i] = ish->get_subset_index(vVertex[i]);
    1137              :         }
    1138              :         if(dim == 2) {
    1139              :                 std::vector<Edge*> vEdges;
    1140            0 :                 CollectEdgesSorted(vEdges, grid, pElem);
    1141            0 :                 vSubsetIndex.resize(vEdges.size());
    1142            0 :                 for(size_t i = 0; i < vEdges.size(); ++i)
    1143            0 :                         vSubsetIndex[i] = ish->get_subset_index(vEdges[i]);
    1144            0 :         }
    1145              :         if(dim == 3) {
    1146              :                 std::vector<Face*> vFaces;
    1147            0 :                 CollectFacesSorted(vFaces, grid, pElem);
    1148            0 :                 vSubsetIndex.resize(vFaces.size());
    1149            0 :                 for(size_t i = 0; i < vFaces.size(); ++i)
    1150            0 :                         vSubsetIndex[i] = ish->get_subset_index(vFaces[i]);
    1151            0 :         }
    1152              : 
    1153              : //      loop requested subset
    1154              :         typename std::map<int, std::vector<BF> >::iterator it;
    1155            0 :         for (it=m_mapVectorBF.begin() ; it != m_mapVectorBF.end(); ++it)
    1156              :         {
    1157              :         //      get subset index
    1158            0 :                 const int bndIndex = (*it).first;
    1159              : 
    1160              :         //      get vector of BF for element
    1161            0 :                 std::vector<BF>& vBF = (*it).second;
    1162              : 
    1163              :         //      clear vector
    1164              :                 vBF.clear();
    1165              : 
    1166              :         //      current number of bf
    1167              :                 size_t curr_bf = 0;
    1168              : 
    1169              :         //      loop sides of element
    1170            0 :                 for(size_t side = 0; side < vSubsetIndex.size(); ++side)
    1171              :                 {
    1172              :                 //      skip non boundary sides
    1173            0 :                         if(vSubsetIndex[side] != bndIndex) continue;
    1174              : 
    1175              :                 //      resize vector
    1176            0 :                         vBF.resize(curr_bf + 1);
    1177              : 
    1178              :                 //  fill BF with data from associated SCV
    1179              :                         BF& bf = vBF[curr_bf];
    1180            0 :                         bf.nodeID =     m_vSCV[side].nodeID;
    1181              : 
    1182              :                         bf.localIP =  m_vSCV[side].vLocIP;
    1183              :                         bf.globalIP = m_vSCV[side].vGlobIP;
    1184              : 
    1185              :                         bf.Normal = m_vSCV[side].Normal;
    1186              :                         //      compute volume
    1187            0 :                         bf.Vol = VecTwoNorm(bf.Normal);
    1188              : 
    1189            0 :                         bf.numCo = m_vSCV[side].numCorners-1;
    1190              : 
    1191              :                         //      compute shapes and grads
    1192            0 :                         m_rTrialSpace.shapes(&(bf.vShape[0]), bf.localIP);
    1193            0 :                         m_rTrialSpace.grads(&(bf.vLocalGrad[0]), bf.localIP);
    1194              : 
    1195              :                         //      get reference mapping
    1196            0 :                         m_mapping.jacobian_transposed_inverse(bf.JtInv, bf.localIP);
    1197            0 :                         bf.detj = m_mapping.sqrt_gram_det(bf.localIP);
    1198              : 
    1199              :                         //      compute global gradients
    1200            0 :                         for(size_t sh = 0 ; sh < bf.num_sh(); ++sh)
    1201              :                                 MatVecMult(bf.vGlobalGrad[sh], bf.JtInv, bf.vLocalGrad[sh]);
    1202              : 
    1203              :                         //      increase curr_bf
    1204              :                         ++curr_bf;
    1205              :                 }
    1206              :         }
    1207            0 : }
    1208              : 
    1209              : #ifdef UG_DIM_2
    1210              : template class DimCRFVGeometry<2, 2>;
    1211              : template class CRFVGeometry<Triangle, 2>;
    1212              : template class CRFVGeometry<Quadrilateral, 2>;
    1213              : #endif
    1214              : 
    1215              : #ifdef UG_DIM_3
    1216              : template class DimCRFVGeometry<3, 3>;
    1217              : template class CRFVGeometry<Triangle, 3>;
    1218              : template class CRFVGeometry<Quadrilateral, 3>;
    1219              : 
    1220              : template class CRFVGeometry<Tetrahedron, 3>;
    1221              : template class CRFVGeometry<Prism, 3>;
    1222              : template class CRFVGeometry<Pyramid, 3>;
    1223              : template class CRFVGeometry<Hexahedron, 3>;
    1224              : #endif
    1225              : 
    1226              : } // end namespace ug
        

Generated by: LCOV version 2.0-1