LCOV - code coverage report
Current view: top level - ugbase/lib_grid/algorithms/extrusion - support3D.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 286 0
Test Date: 2026-01-06 04:48:21 Functions: 0.0 % 44 0

            Line data    Source code
       1              : /*
       2              :  * support3D.h
       3              :  *
       4              :  *  Created on: 31.10.2024
       5              :  *      Author: Markus Knodel
       6              :  */
       7              : 
       8              : #ifndef UGCORE_UGBASE_LIB_GRID_ALGORITHMS_EXTRUSION_SUPPORT3D_H_
       9              : #define UGCORE_UGBASE_LIB_GRID_ALGORITHMS_EXTRUSION_SUPPORT3D_H_
      10              : 
      11              : #include <iostream>
      12              : #include <stdexcept>
      13              : #include <cmath>
      14              : #include <iostream>
      15              : #include <stdlib.h>
      16              : #include <vector>
      17              : #include <assert.h>
      18              : #include <string>
      19              : #include <sstream>
      20              : #include <utility>
      21              : #include <vector>
      22              : #include <type_traits>
      23              : 
      24              : #include "support.h"
      25              : 
      26              : // TODO FIXME
      27              : // verschlanken,
      28              : // Verdoppelungen weg,
      29              : // Namen generalisieren
      30              : // nicht vertex spezifisch zB
      31              : // sondern lowest dim oder so
      32              : 
      33              : namespace ug
      34              : {
      35              : 
      36              : namespace arte
      37              : {
      38              : 
      39              : namespace support
      40              : {
      41              : 
      42              : template<typename ELEMTYP>
      43            0 : bool addElem(std::vector<ELEMTYP> & knownElems, ELEMTYP elemToAdd )
      44              : {
      45              :         bool unknown = true;
      46              : 
      47            0 :         for( ELEMTYP elmKnown : knownElems )
      48              :         {
      49            0 :                 if( elemToAdd == elmKnown )
      50              :                 {
      51              :                         unknown = false;
      52              :                         break;
      53              :                 }
      54              :         }
      55              : 
      56            0 :         if( unknown )
      57            0 :                 knownElems.push_back(elemToAdd);
      58              : 
      59            0 :         return unknown;
      60              : 
      61              : }
      62              : 
      63              : 
      64              : #if 0
      65              : 
      66              : template<typename ELEMTYP, typename INDEX_TYP>
      67              : class ElemInfo
      68              : {
      69              : public:
      70              : 
      71              :         ElemInfo( ELEMTYP const & elem, INDEX_TYP sudo )
      72              :         : m_elem(elem), m_sudo(sudo)
      73              :         {
      74              :         }
      75              : 
      76              : 
      77              : 
      78              : private:
      79              : 
      80              :         ELEMTYP m_elem;
      81              :         INDEX_TYP m_sudo;
      82              : 
      83              :         ElemInfo() {};
      84              : 
      85              : 
      86              : };
      87              : 
      88              : template<
      89              : typename FACETYP,
      90              : typename NORMALTYP,
      91              : typename VOLUMETYP,
      92              : typename EDGETYP,
      93              : typename INDEX_TYP
      94              : >
      95              : class VertexFractureQuadrupel
      96              : {
      97              : public:
      98              : 
      99              :         using ElemInfoFac = ElemInfo<FACETYP,INDEX_TYP>;
     100              : 
     101              :         //face, normal, volume, edge
     102              : 
     103              : //      VertexFractureQuadrupel()
     104              : //      {};
     105              : 
     106              : 
     107              :         VertexFractureQuadrupel( ElemInfoFac const & fracFaceInfo,
     108              :                                                          VOLUMETYP const & attVolume,
     109              :                                                          NORMALTYP const & normal,
     110              :                                                          std::pair<EDGETYP,EDGETYP> const & volCutEdges,
     111              :                                                          std::pair<ElemInfoFac,ElemInfoFac> const & volCutEdgeFaces )
     112              :         : m_fracFaceInfo(fracFaceInfo),
     113              :           m_attVolume(attVolume),
     114              :           m_normal(normal),
     115              :           m_volCutEdges(volCutEdges),
     116              :           m_volCutEdgeFaces(volCutEdgeFaces)
     117              :         {
     118              :         }
     119              : 
     120              :         // todo fixme getter und ggf auch setter, aber vermutlich nur getter implementieren!!!
     121              : 
     122              : private:
     123              : 
     124              : //      FACETYP const getFace() const { return m_full; }
     125              : //      NORMALTYP const getNormal() const { return m_normal; }
     126              : //      VOLUMETYP const getVolume() const { return m_volume; }
     127              : //      EDGETYP const getEdge() const { return m_edge; }
     128              : 
     129              :         ElemInfo<FACETYP,INDEX_TYP> m_fracFaceInfo;
     130              :         VOLUMETYP m_attVolume;
     131              :         NORMALTYP m_normal;
     132              :         std::pair<EDGETYP,EDGETYP> m_volCutEdges;
     133              :         std::pair<ElemInfoFac,ElemInfoFac> m_volCutEdgeFaces;
     134              : 
     135              : //private:
     136              : //
     137              : //      FACETYP m_face;
     138              : //      NORMALTYP m_normal;
     139              : //      VOLUMETYP m_volume;
     140              : //      EDGETYP m_edge;
     141              : 
     142              :         VertexFractureQuadrupel()
     143              :         {};
     144              : };
     145              : #endif
     146              : 
     147              : 
     148              : template <
     149              : typename MANIFELM,
     150              : typename LOWDIMELM,
     151              : typename INDEX_TXP
     152              : >
     153            0 : class AttachedGeneralElem
     154              : {
     155              : public:
     156              :         using PairLowEl = std::pair<LOWDIMELM,LOWDIMELM>;
     157              : 
     158              :         using AttGenElm = AttachedGeneralElem<MANIFELM,LOWDIMELM,INDEX_TXP>;
     159              : 
     160              :         // for fracture elements
     161            0 :         AttachedGeneralElem( MANIFELM const & manifElm,
     162              :                                   PairLowEl const & lowElm
     163              :                                   )
     164              :         :
     165            0 :                 m_manifElm(manifElm), m_pairLowElm(lowElm)
     166              :         {
     167              :         };
     168              : 
     169            0 :         MANIFELM const getManifElm() const { return m_manifElm;}
     170              : //      PairLowEl const getLowElm() const { return m_lowElm; }
     171            0 :         PairLowEl const getPairLowElm() const { return m_pairLowElm; }
     172              : 
     173              :         bool const isNeighboured( AttGenElm const & attElm )
     174              :         const
     175              :         {
     176              : //              MANIFELM manifElmOther = attElm.getManifElm();
     177              :                 PairLowEl lowElmOther = attElm.getPairLowElm();
     178              : //              INDEX_TXP sudoOther = attElm.getSudo();
     179              : 
     180              :                 PairLowEl lowElmThis = this->m_pairLowElm;
     181              : 
     182              :                 std::vector<bool> test;
     183              : 
     184              :                 test.push_back( lowElmOther.first  == lowElmThis.first );
     185              :                 test.push_back( lowElmOther.second  == lowElmThis.first );
     186              :                 test.push_back( lowElmOther.first  == lowElmThis.second );
     187              :                 test.push_back( lowElmOther.second  == lowElmThis.second );
     188              : 
     189              :                 INDEX_TXP countCorr = 0;
     190              : 
     191              :                 for( auto const t : test )
     192              :                 {
     193              :                         if( t )
     194              :                                 countCorr++;
     195              :                 }
     196              : 
     197              :                 if( countCorr == 1 )
     198              :                         return true;
     199              : 
     200              :                 if( countCorr > 1 )
     201              :                         UG_THROW("zu viele gleiche Ecken " << std::endl);
     202              : 
     203              :                 return false;
     204              :         }
     205              : 
     206              :         bool const isNeighbouredAtSpecificSide( AttGenElm const & attElm,
     207              :                                                                                         LOWDIMELM const & specificLDE )
     208              :         const
     209              :         {
     210              :                 PairLowEl lowElmOther = attElm.getPairLowElm();
     211              : 
     212              :                 PairLowEl lowElmThis = this->m_pairLowElm;
     213              : 
     214              :                 // test if the specific element is part of at least
     215              :                 // one of the faces
     216              : 
     217              :                 bool otherFirst = ( lowElmOther.first == specificLDE );
     218              :                 bool otherSecond = ( lowElmOther.second == specificLDE );
     219              : 
     220              :                 bool thisFirst = ( lowElmThis.first == specificLDE );
     221              :                 bool thisSecond = ( lowElmThis.second == specificLDE );
     222              : 
     223              :                 bool isPartOfThisFace = ( thisFirst || thisSecond );
     224              :                 bool isPartOfOtherFace = ( otherFirst || otherSecond );
     225              : 
     226              :                 if( ! isPartOfOtherFace || ! isPartOfThisFace )
     227              :                 {
     228              :                         UG_LOG("not part of one of the faces " << std::endl);
     229              :                         return false;
     230              :                 }
     231              : 
     232              :                 if( otherFirst && thisFirst )
     233              :                 {
     234              :                         if( lowElmOther.first  == lowElmThis.first )
     235              :                                 return true;
     236              :                 }
     237              :                 else if( otherFirst && thisSecond )
     238              :                 {
     239              :                         if( lowElmOther.first  == lowElmThis.second )
     240              :                                 return true;
     241              :                 }
     242              :                 else if( otherSecond && thisFirst )
     243              :                 {
     244              :                         if( lowElmOther.second  == lowElmThis.first )
     245              :                                 return true;
     246              :                 }
     247              :                 else if( otherSecond && thisSecond )
     248              :                 {
     249              :                         if( lowElmOther.second  == lowElmThis.second )
     250              :                                 return true;
     251              :                 }
     252              : 
     253              :                 return false;
     254              :         }
     255              : 
     256            0 :         bool const testIfEquals( AttGenElm const & attElm )
     257              :         const
     258              :         {
     259              :                 MANIFELM manifElmOther = attElm.getManifElm();
     260              :                 PairLowEl lowElmOther = attElm.getPairLowElm();
     261              : 
     262            0 :                 if(    manifElmOther == this->m_manifElm
     263            0 :                         && hasSameEdgePair( lowElmOther )
     264              : //                              && lowElmOther == this->m_pairLowElm
     265              :                 )
     266              :                 {
     267              :                         return true;
     268              :                 }
     269              : 
     270            0 :                 if( manifElmOther == this->m_manifElm && ! hasSameEdgePair( lowElmOther ) )
     271              :                 {
     272              :                         UG_LOG("gleiches face aber andere Ecken???" << std::endl);
     273            0 :                         UG_THROW("gleiches face aber andere Ecken???" << std::endl);
     274              :                 }
     275              : 
     276              :                 return false;
     277              :         }
     278              : 
     279              : 
     280              : protected:
     281              : 
     282              :         MANIFELM m_manifElm;
     283              :         PairLowEl m_pairLowElm;
     284              : 
     285              :         bool const hasSameEdgePair( PairLowEl const & epTwo ) const
     286              :         {
     287              :                 PairLowEl const & epOne = this->m_pairLowElm;
     288              : 
     289            0 :                 if(    ( epOne.first == epTwo.first && epOne.second == epTwo.second )
     290            0 :                         ||      ( epOne.first == epTwo.second && epOne.second == epTwo.first )
     291              :                 )
     292              :                 {
     293              :                         return true;
     294              :                 }
     295              : 
     296              :                 return false;
     297              :         }
     298              : 
     299              : };
     300              : 
     301              : 
     302              : 
     303              : ///////////////////////////////////////////////////////////////////////////////
     304              : 
     305              : 
     306              : // TODO FIXME vertex fracture triplett
     307              : // vereinigen mit  AttachedGeneralElem !!! davon ableiten!!!
     308              : // doppelte Strukturen!!!
     309              : 
     310              : #if 0
     311              : // [[DEPRECATED]]
     312              : // wird abgelöst durch fortschrittlichere Klassen, bald nicht mehr nötig
     313              : template <
     314              : typename MANIFOLDTYP, // 3D: Face
     315              : typename INDEXTYP, // int oder unsinged int oder short oder unsigned short etc
     316              : typename FULLDIMTYP, // 3D: Volume
     317              : typename SENKRECHTENTYP, // 3D und 2D: ug::vector3
     318              : typename LOWDIMTYP // 3D: Edge (2D nicht benötigt)
     319              : >
     320              : class VertexFractureTripleMF
     321              : : public AttachedGeneralElem<MANIFOLDTYP,LOWDIMTYP,INDEXTYP>
     322              : {
     323              : 
     324              : private:
     325              :         using AttGenEl = AttachedGeneralElem<MANIFOLDTYP,LOWDIMTYP,INDEXTYP>;
     326              : 
     327              : public:
     328              : 
     329              :         using PairLowEl = std::pair<LOWDIMTYP,LOWDIMTYP>;
     330              : 
     331              :         VertexFractureTripleMF( MANIFOLDTYP const & manifElm, INDEXTYP sudo,
     332              :                                                         FULLDIMTYP const & fullElm,
     333              :                                                         SENKRECHTENTYP const & normal,
     334              :                                                         PairLowEl const & pairLowElm )
     335              :         : //m_manifElm(manifElm),
     336              :           AttGenEl(manifElm,pairLowElm),
     337              :           m_sudo(sudo), m_fullElm(fullElm),
     338              :           m_normal(normal), m_newNormal(normal)
     339              : //              ,
     340              : //        m_pairLowElm(pairLowElm)
     341              :         {
     342              :         };
     343              : 
     344              : //      MANIFOLDTYP const getManifElm() const { return m_manifElm; }
     345              : 
     346              :         INDEXTYP const getSudoElm() const { return m_sudo; }
     347              : 
     348              :         FULLDIMTYP const getFullElm() const { return m_fullElm; }
     349              : 
     350              :         SENKRECHTENTYP const getNormal() const { return m_normal; }
     351              : 
     352              :         // TODO FIXME unklar, ob neue Normale irgendwo gebraucht wird
     353              :         // falls notwendig in die Fracture Klasse einführen,
     354              :         // die diese Klasse hier mittelfristig ablösen soll vollständig
     355              :         void setNewNormal( SENKRECHTENTYP const & chNorml ) { m_newNormal = chNorml; }
     356              : 
     357              :         SENKRECHTENTYP const getNewNormal() const { return m_newNormal; }
     358              : 
     359              : //      PairLowEl const getPairLowElm() const { return m_pairLowElm; }
     360              : 
     361              : private:
     362              : 
     363              : //      MANIFOLDTYP m_manifElm;
     364              :         INDEXTYP m_sudo;
     365              :         FULLDIMTYP m_fullElm;
     366              :         SENKRECHTENTYP  m_normal;
     367              :         SENKRECHTENTYP  m_newNormal;
     368              : //      PairLowEl m_pairLowElm;
     369              : 
     370              :         VertexFractureTripleMF()
     371              :         {};
     372              : 
     373              : };
     374              : #endif
     375              : 
     376              : //////////////////////////////////////////////////////////////////
     377              : 
     378              : // TODO FIXME das muss angepasst werden, ist noch wie für 2D Fall bisher
     379              : enum FracTypVol { SingleFrac = 2, TEnd = 3, XCross = 4 };
     380              : 
     381              : template < typename VRT, typename IndTyp >
     382            0 : class CrossingVertexInfoVol
     383              : {
     384              : 
     385              : public:
     386              : 
     387              :         CrossingVertexInfoVol( VRT const & crossVrt, FracTypVol fracTyp )
     388              :         : m_crossVrt(crossVrt), m_fracTyp( fracTyp ),
     389              :           m_vecShiftedVrts(std::vector<VRT>())
     390              :         ,  m_vecShiftedVrtsWithTypInf(std::vector<std::pair<VRT,bool>>())
     391              :         , m_numberAtFreeSide(0)
     392              :         {
     393              :         }
     394              : 
     395              :         VRT getCrossVertex() const { return m_crossVrt; }
     396              : 
     397              :         FracTypVol getFracTyp() const { return m_fracTyp; }
     398              : 
     399              :         void addShiftVrtx( VRT const & vrt, bool isAtFreeSide = false )
     400              :         {
     401              :                 m_vecShiftedVrts.push_back(vrt);
     402              : 
     403              : //              if( m_fracTyp == TEnd )
     404              : //              {
     405              : //                      std::pair<VRT, bool > addSVI( vrt, isAtFreeSide );
     406              : //                      m_vecShiftedVrtsWithTypInf.push_back(addSVI);
     407              : //
     408              : //                      if( isAtFreeSide )
     409              : //                              m_numberAtFreeSide++;
     410              : //
     411              : //                      if( m_numberAtFreeSide > 1 )
     412              : //                              UG_THROW("was ist das fuer ein T Ende" << std::endl);
     413              : //              }
     414              : 
     415              :         }
     416              : 
     417              :         void setShiftVrtx( std::vector<VRT> const & vecVrt ) { m_vecShiftedVrts = vecVrt; }
     418              : 
     419              :         std::vector<VRT> getVecShiftedVrts() const
     420              :         {
     421              :                 return m_vecShiftedVrts;
     422              :         }
     423              : 
     424              :         std::vector<std::pair<VRT,bool>> getVecShiftedVrtsWithTypInfo() const
     425              :         {
     426              : //              if( m_fracTyp != TEnd )
     427              : //                      UG_THROW("fuer Kreuz nicht erlaubt " << std::endl);
     428              : 
     429              :                 return m_vecShiftedVrtsWithTypInf;
     430              :         }
     431              : 
     432              : 
     433              : private:
     434              : 
     435              :         VRT m_crossVrt;
     436              :         std::vector<VRT> m_vecShiftedVrts;
     437              :         std::vector<std::pair<VRT,bool>> m_vecShiftedVrtsWithTypInf;
     438              :         FracTypVol m_fracTyp;
     439              :         IndTyp m_numberAtFreeSide;
     440              : };
     441              : 
     442              : ///////////////////////////////////////////////////////////////////////////////
     443              : 
     444              : 
     445              : 
     446              : // info for a vertex: face and attached edges, for fractures only
     447              : //  derived from the similar class without fracture property!
     448              : template <
     449              : typename MANIFELM,
     450              : typename LOWDIMELM,
     451              : typename INDEX_TXP,
     452              : typename NORMAL_VEC
     453              : >
     454            0 : class AttachedFractElem
     455              : : public AttachedGeneralElem<MANIFELM,LOWDIMELM,INDEX_TXP>
     456              : // TODO FIXME derive from AttachedGeneralElem
     457              : {
     458              : public:
     459              :         using PairLowEl = std::pair<LOWDIMELM,LOWDIMELM>;
     460              : 
     461              :         using AttFractElm = AttachedFractElem<MANIFELM,LOWDIMELM,INDEX_TXP,NORMAL_VEC>;
     462              : 
     463              :         using AttGenElm = AttachedGeneralElem<MANIFELM,LOWDIMELM,INDEX_TXP>;
     464              : 
     465              :         // for fracture elements
     466            0 :         AttachedFractElem( MANIFELM const & manifElm,
     467              :                                   PairLowEl & lowElm,
     468              :                                   INDEX_TXP sudo,
     469              :                                   NORMAL_VEC const & normalVec )
     470              :         :
     471              :                 AttGenElm(manifElm,lowElm),
     472              :                 //m_manifElm(manifElm), m_lowElm(lowElm),
     473            0 :                 m_sudo(sudo),
     474              :                 m_normalVec(normalVec)
     475              :         {
     476              :         };
     477              : 
     478              : 
     479              : //      MANIFELM const getManifElm() const { return m_manifElm;}
     480              : //      PairLowEl const getLowElm() const { return m_lowElm; }
     481            0 :         INDEX_TXP const getSudo() const { return m_sudo; };
     482              : 
     483              :         NORMAL_VEC const getNormalVec() const { return m_normalVec; }
     484              : 
     485              :         bool const testIfEquals( AttFractElm const & attElm )
     486              :         const
     487              :         {
     488            0 :                 bool geomEqu = AttGenElm::testIfEquals(attElm);
     489              : 
     490              : //              MANIFELM manifElmOther = attElm.getManifElm();
     491              : //              PairLowEl lowElmOther = attElm.getLowElm();
     492              :                 INDEX_TXP sudoOther = attElm.getSudo();
     493              : 
     494              : //              if(    manifElmOther == this->m_manifElm
     495              : //                      && lowElmOther == this->m_lowElm
     496              : //                      && sudoOther == this->m_sudo
     497              : //              )
     498              : //              {
     499              : //                      return true;
     500              : //              }
     501              : 
     502            0 :                 if( geomEqu && sudoOther == this->m_sudo )
     503              :                 {
     504              :                         return true;
     505              :                 }
     506              : 
     507              :                 return false;
     508              :         }
     509              : 
     510              : 
     511              : //      bool const testIfEquals( AttachedFractElem<MANIFELM,LOWDIMELM,INDEX_TXP> const & attElm )
     512              : //      const
     513              : //      {
     514              : //              MANIFELM manifElmOther = attElm.getManifElm();
     515              : //              PairLowEl lowElmOther = attElm.getLowElm();
     516              : //              INDEX_TXP sudoOther = attElm.getSudo();
     517              : //
     518              : //              if(    manifElmOther == this->m_manifElm
     519              : //                      && lowElmOther == this->m_lowElm
     520              : //                      && sudoOther == this->m_sudo
     521              : //              )
     522              : //              {
     523              : //                      return true;
     524              : //              }
     525              : //
     526              : //              return false;
     527              : //      }
     528              : 
     529              : //      bool const isNeighboured(  AttachedFractElem<MANIFELM,LOWDIMELM,INDEX_TXP> const & attElm )
     530              : //      const
     531              : //      {
     532              : ////            MANIFELM manifElmOther = attElm.getManifElm();
     533              : //              PairLowEl lowElmOther = attElm.getLowElm();
     534              : ////            INDEX_TXP sudoOther = attElm.getSudo();
     535              : //
     536              : //              PairLowEl lowElmThis = this->m_lowElm;
     537              : //
     538              : //              std::vector<bool> test;
     539              : //
     540              : //              test.push_back( lowElmOther.first  == lowElmThis.first );
     541              : //              test.push_back( lowElmOther.second  == lowElmThis.first );
     542              : //              test.push_back( lowElmOther.first  == lowElmThis.second );
     543              : //              test.push_back( lowElmOther.second  == lowElmThis.second );
     544              : //
     545              : //              INDEX_TXP countCorr = 0;
     546              : //
     547              : //              for( auto const t : test )
     548              : //              {
     549              : //                      if( t )
     550              : //                              countCorr++;
     551              : //              }
     552              : //
     553              : //              if( countCorr == 1 )
     554              : //                      return true;
     555              : //
     556              : //              if( countCorr > 1 )
     557              : //                      UG_THROW("zu viele gleiche Ecken " << std::endl);
     558              : //
     559              : //              return false;
     560              : //      }
     561              : //
     562              : //      bool const isNeighbouredAtSpecificSide( AttachedFractElem<MANIFELM,LOWDIMELM,INDEX_TXP> const & attElm,
     563              : //                                                                                      LOWDIMELM const & specificLDE )
     564              : //      const
     565              : //      {
     566              : //              PairLowEl lowElmOther = attElm.getLowElm();
     567              : //
     568              : //              PairLowEl lowElmThis = this->m_lowElm;
     569              : //
     570              : //              // test if the specific element is part of at least
     571              : //              // one of the faces
     572              : //
     573              : //              bool otherFirst = ( lowElmOther.first == specificLDE );
     574              : //              bool otherSecond = ( lowElmOther.second == specificLDE );
     575              : //
     576              : //              bool thisFirst = ( lowElmThis.first == specificLDE );
     577              : //              bool thisSecond = ( lowElmThis.second == specificLDE );
     578              : //
     579              : //              bool isPartOfThisFace = ( thisFirst || thisSecond );
     580              : //              bool isPartOfOtherFace = ( otherFirst || otherSecond );
     581              : //
     582              : //              if( ! isPartOfOtherFace || ! isPartOfThisFace )
     583              : //              {
     584              : //                      UG_LOG("not part of one of the faces " << std::endl);
     585              : //                      return false;
     586              : //              }
     587              : //
     588              : //              if( otherFirst && thisFirst )
     589              : //              {
     590              : //                      if( lowElmOther.first  == lowElmThis.first )
     591              : //                              return true;
     592              : //              }
     593              : //              else if( otherFirst && thisSecond )
     594              : //              {
     595              : //                      if( lowElmOther.first  == lowElmThis.second )
     596              : //                              return true;
     597              : //              }
     598              : //              else if( otherSecond && thisFirst )
     599              : //              {
     600              : //                      if( lowElmOther.second  == lowElmThis.first )
     601              : //                              return true;
     602              : //              }
     603              : //              else if( otherSecond && thisSecond )
     604              : //              {
     605              : //                      if( lowElmOther.second  == lowElmThis.second )
     606              : //                              return true;
     607              : //              }
     608              : //
     609              : //              return false;
     610              : //      }
     611              : 
     612              : private:
     613              : //      MANIFELM m_manifElm;
     614              : //      PairLowEl m_lowElm;
     615              :         INDEX_TXP m_sudo;
     616              :         NORMAL_VEC m_normalVec;
     617              : 
     618              : 
     619              : };
     620              : 
     621              : //////////////////////////////////////////////////////////////////////////////
     622              : 
     623              : // a quasi exact double, but only used for boundary faces, to avoid mismatch with frac faces
     624              : template <
     625              : typename MANIFELM,
     626              : typename LOWDIMELM,
     627              : typename INDEX_TXP,
     628              : typename NORMAL_VEC
     629              : >
     630              : class AttachedBoundryElem
     631              : : public AttachedFractElem<MANIFELM,LOWDIMELM,INDEX_TXP,NORMAL_VEC>
     632              : {
     633              : public:
     634              :         using PairLowEl = std::pair<LOWDIMELM,LOWDIMELM>;
     635              : 
     636              :         using AttBndryElm = AttachedBoundryElem<MANIFELM,LOWDIMELM,INDEX_TXP,NORMAL_VEC>;
     637              : 
     638              :         using AttFractElm = AttachedFractElem<MANIFELM,LOWDIMELM,INDEX_TXP,NORMAL_VEC>;
     639              : 
     640              : 
     641              :         // for boundary elements
     642              :         AttachedBoundryElem( MANIFELM const & manifElm,
     643              :                                   PairLowEl & lowElm,
     644              :                                   INDEX_TXP sudo,
     645              :                                   NORMAL_VEC const & normalVec )
     646              :         :
     647              :                 AttFractElm( manifElm, lowElm, sudo, normalVec)
     648              :         {
     649              :         };
     650              : };
     651              : 
     652              : ////////////////////////////////////////////////////////////////////////////
     653              : 
     654              : // class to help count and store a bool and a number of templete type
     655              : // comparable to std::pair<bool,int> but more dedicated to the specific aim
     656              : // TODO FIXME adapt for 3D case, figure out if inner end, and number of fracs sourrounding
     657              : // CAUTION is also used for edges, but still uses
     658              : // vertex as indicator - name should be made more flexible
     659              : 
     660              : // die meisten Funktionen in dieser Klasse:
     661              : // DEPRECATED, to be replaced in near future everywhere, not really useful any more
     662              : // due to the Stasi algorithm
     663              : // [[deprecated]] ab C++14, leider nicht passend zur Konvention C++11
     664              : // die Sudo-Liste wollen wir aber lassen
     665              : template<
     666              : typename T,
     667              : typename ATT_ELEM
     668              : >
     669            0 : class VertexFracturePropertiesVol
     670              : {
     671              : public:
     672              : 
     673              :         using pairTB = std::pair<T,bool>;
     674              :         using VecPairTB = std::vector<pairTB>;
     675              : 
     676              : 
     677              : //      VertexFracturePropertiesVol( bool isBndFracVertex,  T numberCrossingFracsInVertex )
     678              : //      : m_isBndFracVertex(isBndFracVertex), m_numberCountedFracsInVertex(numberCrossingFracsInVertex)
     679              : //      {
     680              : //      };
     681              : 
     682              :         // DEPRECATED, kann entfernt werden vermutlich, CHECK, TODO FIXME
     683              :         enum VrtxFracStatus { noFracSuDoAtt = 0,
     684              :                                                   oneFracSuDoAtt = 1,
     685              :                                                   twoFracSuDoAtt = 2,
     686              :                                                   threeFracSuDoAtt = 3 };
     687              : 
     688            0 :         VertexFracturePropertiesVol()
     689            0 :         : m_isBndFracVertex(false), m_numberCountedFracsInVertex(0),
     690            0 :           m_status( noFracSuDoAtt ),
     691              :           m_sudoList( std::vector<T>() ) //,
     692              : //        m_sudosClosed(VecPairTB()),
     693              : //        m_vecAttElem(std::vector<ATT_ELEM>())
     694              : //              VertexFracturePropertiesVol( false, 0 )
     695              :         {
     696              :         };
     697              : 
     698              :         void setIsBndFracVertex( bool iBDV = true )
     699              :         {
     700            0 :                 m_isBndFracVertex = iBDV;
     701            0 :         }
     702              : 
     703              :         void setNumberCrossingFracsInVertex( T const & nCFIV )
     704              :         {
     705              :                 m_numberCountedFracsInVertex = nCFIV;
     706              :         }
     707              : 
     708              :         bool getIsBndFracVertex()
     709              :         {
     710            0 :                 return m_isBndFracVertex;
     711              :         }
     712              : 
     713              : //      T getCountedNumberFracsInVertex()
     714              : //      {
     715              : //              return m_numberCountedFracsInVertex;
     716              : //      }
     717              : 
     718              : 
     719              :         T getNumberFracEdgesInVertex()
     720              :         {
     721            0 :                 return m_numberCountedFracsInVertex;
     722              :         }
     723              : 
     724              : //      T getNumberCrossingFracsInVertex()
     725              : //  {
     726              : //              if( m_isBndFracVertex )
     727              : //                      return m_numberCountedFracsInVertex;
     728              : //
     729              : //              // for inner vertices, each edge passed when
     730              : //              // fractures are counted along their edges
     731              : //              // that the vertizes get hit twice for each fracture run
     732              : //              // only for boundary vertices, this happens only once per fracture
     733              : //              T multipeInnerHits = 2;
     734              : //
     735              : //              T rest = m_numberCountedFracsInVertex % multipeInnerHits;
     736              : //
     737              : //              if( rest != 0 )
     738              : //              {
     739              : ////                    UG_THROW("Expand layers: rest division frac counting not zero " << m_numberCountedFracsInVertex << std::endl);
     740              : //
     741              : //                      throw std::runtime_error("error");
     742              : //
     743              : //                      return 0;
     744              : //              }
     745              : //
     746              : //              return m_numberCountedFracsInVertex / multipeInnerHits;
     747              : //  }
     748              : 
     749              :         VertexFracturePropertiesVol & operator++( int a )
     750              :         {
     751            0 :                 m_numberCountedFracsInVertex++;
     752              :                 return *this;
     753              :         }
     754              : 
     755              : 
     756              :         VrtxFracStatus getVrtxFracStatus()
     757              :         {
     758              :                 return m_status;
     759              :         }
     760              : 
     761              :         // caution: returns false if sudo already known, but no problem, feature, not bug
     762              :         // so never stop the program if false returned here, this is good news
     763            0 :         bool addFractSudo( T const & sudo )
     764              :         {
     765              :                 bool alreadyInList = false;
     766              : 
     767            0 :                 for( auto const & availSudo : m_sudoList )
     768              :                 {
     769            0 :                         if( sudo == availSudo )
     770              :                                 alreadyInList = true;
     771              :                 }
     772              : 
     773            0 :                 if( ! alreadyInList )
     774              :                 {
     775            0 :                         m_sudoList.push_back( sudo );
     776              :                 }
     777              : 
     778            0 :                 return adaptVrtxFracStatus();
     779              :         }
     780              : 
     781              :         // setter private to avoid abusive use
     782              :         std::vector<T> const getSudoList() const
     783              :         {
     784            0 :                 return m_sudoList;
     785              :         }
     786              : 
     787              : //      bool setIsAClosedFracture( T sudoNow, bool isClosedNow )
     788              : //      {
     789              : //
     790              : //              T alreadyKnownMult = 0;
     791              : //
     792              : //              for( auto & suSu : m_sudosClosed )
     793              : //              {
     794              : //                      T & sudoVal = suSu.first;
     795              : //                      bool & isClosedVal = suSu.second;
     796              : //
     797              : //                      if( sudoVal == sudoNow )
     798              : //                      {
     799              : //                              alreadyKnownMult++;
     800              : //
     801              : //                              UG_LOG("Reassign sudo surround " << std::endl);
     802              : //
     803              : //                              if( isClosedVal != isClosedNow )
     804              : //                                      UG_THROW("change property sudo surrounded, why?" << std::endl);
     805              : //
     806              : //                              isClosedVal = isClosedNow;
     807              : //                      }
     808              : //              }
     809              : //
     810              : //              if( alreadyKnownMult == 0 )
     811              : //              {
     812              : //                      pairTB infoSudoSurr( sudoNow, isClosedNow );
     813              : //
     814              : //                      m_sudosClosed.push_back( infoSudoSurr );
     815              : //
     816              : //              }
     817              : //              else if( alreadyKnownMult > 1 )
     818              : //              {
     819              : //                      UG_THROW("zu oft bekannt " << std::endl);
     820              : //                      return false;
     821              : //              }
     822              : //
     823              : //              // check if now correct
     824              : //
     825              : //              T testKnownFine = 0;
     826              : //
     827              : //              for( auto const & suSu : m_sudosClosed )
     828              : //              {
     829              : //                      T & sudoVal = suSu.first;
     830              : //                      bool & isClosedVal = suSu.second;
     831              : //
     832              : //                      if( sudoVal == sudoNow )
     833              : //                      {
     834              : //                              testKnownFine++;
     835              : //
     836              : //                              if( isClosedVal != isClosedNow )
     837              : //                              {
     838              : //                                      UG_THROW("NOT set property sudo surrounded, why?" << std::endl);
     839              : //                                      return false;
     840              : //                              }
     841              : //
     842              : //                      }
     843              : //              }
     844              : //
     845              : //              if( testKnownFine == 0 || testKnownFine > 1 )
     846              : //              {
     847              : //                      UG_THROW("immer noch nicht bekannt?" << std::endl);
     848              : //                      return false;
     849              : //
     850              : //              }
     851              : //
     852              : //              return true;
     853              : //      }
     854              : //
     855              : //      bool getIsAClosedFracture( T sudoNow )
     856              : //      {
     857              : //              T foundMultpl = 0;
     858              : //
     859              : //              bool isClosedReturn = false;
     860              : //
     861              : //              for( auto const & suSu : m_sudosClosed )
     862              : //              {
     863              : //                      T const & sudoVal = suSu.first;
     864              : //                      bool const & isClosedVal = suSu.second;
     865              : //
     866              : //                      if( sudoVal == sudoNow )
     867              : //                      {
     868              : //                              foundMultpl++;
     869              : //                              isClosedReturn = isClosedVal;
     870              : //                      }
     871              : //              }
     872              : //
     873              : //              if( foundMultpl != 1 )
     874              : //              {
     875              : //                      UG_THROW("not known status closed or not sudo" << std::endl);
     876              : //                      return false;
     877              : //              }
     878              : //
     879              : //              return isClosedReturn;
     880              : //      }
     881              : //
     882              : //      bool setInfoAllFractureSudosIfClosed( VecPairTB const & sudosClosed )
     883              : //      {
     884              : //              m_sudosClosed = sudosClosed;
     885              : //
     886              : //              return true;
     887              : //      }
     888              : //
     889              : //      VecPairTB const getInfoAllFracSudosIfClosed() const
     890              : //      {
     891              : //              return m_sudosClosed;
     892              : //      }
     893              : //
     894              : //      // if all open or closed
     895              : //      template<bool B>
     896              : //      bool const getInfoAllFracturesSameClosedState() const
     897              : //      {
     898              : //              bool allFracsSame = true;
     899              : //
     900              : //              for( auto const & suSu : m_sudosClosed )
     901              : //              {
     902              : //                      //T const & sudoVal = suSu.first;
     903              : //                      bool const & isClosedVal = suSu.second;
     904              : //
     905              : //                      if( isClosedVal != B )
     906              : //                              allFracsSame = false;
     907              : //              }
     908              : //
     909              : //              return allFracsSame;
     910              : //      }
     911              : 
     912              :         // DEPRECATED; REMOVE
     913              : //      bool addAttachedFractElem( ATT_ELEM const & attElem )
     914              : //      {
     915              : //              bool alreadyKnown = false;
     916              : //
     917              : //              for( auto const & aE : m_vecAttElem )
     918              : //              {
     919              : //                      if( aE.testIfEquals(attElem) )
     920              : //                              alreadyKnown = true;
     921              : //              }
     922              : //
     923              : //              if( ! alreadyKnown )
     924              : //                      m_vecAttElem.push_back(attElem);
     925              : //
     926              : //              // returns true if ads it, false if no need as known
     927              : //              return ! alreadyKnown;
     928              : //      }
     929              : 
     930              : //      std::vector<ATT_ELEM> const & getAllAttachedFractElems()
     931              : //      const
     932              : //      {
     933              : //              return m_vecAttElem;
     934              : //      }
     935              : 
     936              : private:
     937              :         bool m_isBndFracVertex;
     938              :         T m_numberCountedFracsInVertex;
     939              : 
     940              :         VrtxFracStatus m_status;
     941              : 
     942              :         static VrtxFracStatus constexpr m_maxStatus = VrtxFracStatus::threeFracSuDoAtt;
     943              : 
     944              :         std::vector<T> m_sudoList;
     945              : 
     946              :         // better private, to avoid confusion
     947              :         bool setVrtxFracStatus( VrtxFracStatus status )
     948              :         {
     949              :                 m_status = status;
     950              : 
     951              :                 if( status < noFracSuDoAtt || status > threeFracSuDoAtt )
     952              :                         return false;
     953              : 
     954              :                 return true;
     955              :         }
     956              : 
     957            0 :         bool adaptVrtxFracStatus()
     958              :         {
     959              :                 auto sudosNum = m_sudoList.size();
     960            0 :                 if( sudosNum > static_cast<T>( m_maxStatus ) )
     961              :                 {
     962            0 :                         UG_THROW("zu viele subdomains crossing in one Punkt" << std::endl);
     963              :                         return false;
     964              :                 }
     965              : 
     966            0 :                 m_status = static_cast<VrtxFracStatus>(sudosNum);
     967              : 
     968              :                 return true;
     969              :         }
     970              : 
     971              : //      VecPairTB m_sudosClosed;
     972              : 
     973              :         bool setSudoList( std::vector<T> const & sudoList )
     974              :         {
     975              :                 m_sudoList = sudoList;
     976              : 
     977              :                 return true;
     978              :         }
     979              : 
     980              : //      std::vector<ATT_ELEM> m_vecAttElem;
     981              : 
     982              : };
     983              : 
     984              : 
     985              : // intention, explained for volume:
     986              : template<
     987              : typename FULLDIM_ELEM,
     988              : typename MANIFELM,
     989              : typename LOWDIMELM,
     990              : typename INDEX_TXP,
     991              : typename NORMAL_VEC
     992              : >
     993              : class AttachedFullDimElemInfo
     994              : {
     995              : 
     996              : public:
     997              : 
     998              :         using AttachedFractManifElemInfo = AttachedFractElem<MANIFELM,LOWDIMELM,INDEX_TXP,NORMAL_VEC>;
     999              :         using AttachedGenerManifElemInfo = AttachedGeneralElem<MANIFELM,LOWDIMELM,INDEX_TXP>;
    1000              :         using AttachedBndryManifElemInfo = AttachedBoundryElem<MANIFELM,LOWDIMELM,INDEX_TXP,NORMAL_VEC>;
    1001              : 
    1002              :         using VecAttachedFractManifElemInfo = std::vector<AttachedFractManifElemInfo>;
    1003              :         using VecAttachedGenerManifElemInfo = std::vector<AttachedGenerManifElemInfo>;
    1004              :         using VecAttachedBndryManifElemInfo = std::vector<AttachedBndryManifElemInfo>;
    1005              : 
    1006              :         using AttFullDimElmInfo = AttachedFullDimElemInfo<FULLDIM_ELEM,MANIFELM,LOWDIMELM,INDEX_TXP,NORMAL_VEC>;
    1007              : 
    1008            0 :         AttachedFullDimElemInfo( FULLDIM_ELEM const & fullDimElm )
    1009            0 :         : m_fullDimElm(fullDimElm),
    1010            0 :           m_elementMarked(false),
    1011              :           m_vecFractManifElm(VecAttachedFractManifElemInfo()),
    1012              :           m_vecUnclosedFractManifElm(VecAttachedFractManifElemInfo()),
    1013              : //        m_vecFractManifElmTouchInfo(VecAttFractManifElmTouchInf()),
    1014              : //        m_allSidesTouched(false),
    1015              :           m_vecGenerManifElm(VecAttachedGenerManifElemInfo()),
    1016              :           m_vecBndryManifElm(VecAttachedBndryManifElemInfo())
    1017              : //        m_vecGenerManifElmTouchInfo(VecAttFractManifElmTouchInf())
    1018              : //        m_vecInnerSegmentManifElm(VecAttachedGenerManifElemInfo())
    1019              :         {
    1020              :         }
    1021              : 
    1022              :         FULLDIM_ELEM const getFulldimElem() const
    1023              :         {
    1024            0 :                 return m_fullDimElm;
    1025              :         }
    1026              : 
    1027              :         bool const hasSameFulldimElem( AttFullDimElmInfo const & otherFullDimElmInf )
    1028              :         const
    1029              :         {
    1030              :                 FULLDIM_ELEM otherFullDimElm = otherFullDimElmInf.getFulldimElem();
    1031              : 
    1032            0 :                 return ( otherFullDimElm == m_fullDimElm );
    1033              :         }
    1034              : 
    1035            0 :         bool const isMarked() const { return m_elementMarked; }
    1036              : 
    1037            0 :         void markIt() { m_elementMarked = true; } // to allow in loop to be start element
    1038              : 
    1039              :         bool const hasFracture() const { return ( m_vecFractManifElm.size() > 0 ); }
    1040              : 
    1041              :         bool const hasUnclosedFracture() const { return ( m_vecUnclosedFractManifElm.size() > 0 ); }
    1042              : 
    1043              :         bool addFractManifElem( AttachedFractManifElemInfo const & manifFractElm, Grid & grid )
    1044              :         {
    1045            0 :                 return addManifElem( manifFractElm, m_vecFractManifElm, grid );
    1046              :         }
    1047              : 
    1048              :         bool addGenerManifElem( AttachedGenerManifElemInfo const & manifGenerElm, Grid & grid )
    1049              :         {
    1050              : //              static_assert(std::is_same<AttachedGenerManifElemInfo, decltype( manifGenerElm ) >::value);
    1051              : 
    1052            0 :                 return addManifElem( manifGenerElm, m_vecGenerManifElm, grid );
    1053              :         }
    1054              : 
    1055              :         bool addBndryManifElem( AttachedBndryManifElemInfo const & manifBndryElm, Grid & grid )
    1056              :         {
    1057            0 :                 return addManifElem( manifBndryElm, m_vecBndryManifElm, grid );
    1058              :         }
    1059              : 
    1060              :         // necessary to avoid stupid casting from derived class AttachedFractManifElemInfo
    1061              :         // else, addGenerManifElem would also eat objects of derived class
    1062              :         // however not it only accepts explicit base class objects
    1063              :         template <typename NOGEN>
    1064              :         bool addGenerManifElem( NOGEN const & noGener, Grid & grid )
    1065              :         = delete;
    1066              : 
    1067              :         template <typename NOGEN>
    1068              :         bool addBndryManifElem( NOGEN const & noGener, Grid & grid )
    1069              :         = delete;
    1070              : 
    1071              : 
    1072              : //      // will form new "surface" of next inner round in a segment
    1073              : //      bool addInnerSegmentManifElem( AttachedGenerManifElemInfo const & manifInnerSegmentElm, Grid & grid )
    1074              : //      {
    1075              : //              return addManifElem( manifInnerSegmentElm, m_vecInnerSegmentManifElm, grid );
    1076              : //      }
    1077              : //
    1078              : //      template <typename NOGEN>
    1079              : //      bool addInnerSegmentElem( NOGEN const & noGener, Grid & grid )
    1080              : //      = delete;
    1081              : 
    1082              : 
    1083              : 
    1084              : //      bool addFractureManifElem( AttachedFractManifElemInfo const & manifElm, Grid & grid )
    1085              : //      {
    1086              : //              // Caution: first test if manifold elem is at all part of the fulldim elem manifols
    1087              : //              // if not, return false directly
    1088              : //
    1089              : //              if( ! fullDimElmContainsManif( manifElm.getManifElm(), grid ) )
    1090              : //                      return false;
    1091              : //
    1092              : //              // if manif elem is in principle part of the fulldim elem manifolds,
    1093              : //              // then we need to check if it is already integrated
    1094              : //
    1095              : //              bool hasElemAlready = false;
    1096              : //
    1097              : //
    1098              : //              for( auto const & me : m_vecFractManifElm )
    1099              : //              {
    1100              : //                      if( manifElm.testIfEquals(me) )
    1101              : //                      {
    1102              : //                              hasElemAlready = true;
    1103              : //                              break;
    1104              : //                      }
    1105              : //              }
    1106              : //
    1107              : //              if( ! hasElemAlready )
    1108              : //              {
    1109              : //                      m_vecFractManifElm.push_back( manifElm );
    1110              : //
    1111              : ////                    AttFractManifElmTouchInf pamei( manifElm, false );
    1112              : ////
    1113              : ////                    m_vecFractManifElmTouchInfo.push_back(pamei);
    1114              : //              }
    1115              : //
    1116              : //              return ! hasElemAlready;
    1117              : //      }
    1118              : 
    1119              :         VecAttachedFractManifElemInfo const getVecFractManifElem() const
    1120              :         {
    1121            0 :                 return m_vecFractManifElm;
    1122              :         }
    1123              : 
    1124              :         VecAttachedFractManifElemInfo const getVecUnclosedFractManifElem() const
    1125              :         {
    1126            0 :                 return m_vecUnclosedFractManifElm;
    1127              :         }
    1128              : 
    1129              : 
    1130              :         VecAttachedGenerManifElemInfo const getVecGenerManifElem() const
    1131              :         {
    1132            0 :                 return m_vecGenerManifElm;
    1133              :         }
    1134              : 
    1135              :         VecAttachedBndryManifElemInfo const getVecBndryManifElem() const
    1136              :         {
    1137            0 :                 return m_vecBndryManifElm;
    1138              :         }
    1139              : 
    1140              : 
    1141              :         bool const searchGenerManifElem( AttachedGenerManifElemInfo const & manifGenerElemOther, bool eraseFound = true )
    1142              :         {
    1143              :                 bool found = searchManifElem( manifGenerElemOther, m_vecGenerManifElm, eraseFound );
    1144              : 
    1145              :                 if( found && eraseFound )
    1146              :                 {
    1147              :                         m_elementMarked = true;
    1148              :                 }
    1149              : 
    1150              :                 return found;
    1151              :         }
    1152              : 
    1153            0 :         bool const testFullDimElmNeighbour( AttFullDimElmInfo const & attFullDimElmInfOther, bool eraseFoundManif = true )
    1154              :         {
    1155              :                 VecAttachedGenerManifElemInfo const & vecGenerManifElmOther = attFullDimElmInfOther.getVecGenerManifElem();
    1156              : 
    1157              :                 bool manifNeighbored = false;
    1158              : 
    1159            0 :                 for( AttachedGenerManifElemInfo const & generManifElemOther : vecGenerManifElmOther )
    1160              :                 {
    1161            0 :                         if(     searchManifElem( generManifElemOther, m_vecGenerManifElm, eraseFoundManif ) )
    1162              :                                 manifNeighbored = true;
    1163              : 
    1164              :                 }
    1165              : 
    1166            0 :                 if( manifNeighbored && eraseFoundManif )
    1167              :                 {
    1168            0 :                         m_elementMarked = true;
    1169              :                 }
    1170              : 
    1171            0 :                 return manifNeighbored;
    1172            0 :         }
    1173              : 
    1174              : 
    1175              :         template <typename NOGEN>
    1176              :         bool searchGenerManifElem( NOGEN const & manifGenerElemOther, bool eraseFound ) = delete;
    1177              : 
    1178              : //      bool const searchFractManifElem( AttachedFractManifElemInfo const & manifFractElemOther, bool eraseFound = true )
    1179            0 :         bool const searchFractManifElem( AttachedFractManifElemInfo const & manifFractElemOther, bool shiftToUnclosedFracts = true )
    1180              :         {
    1181            0 :                 bool found = searchManifElem( manifFractElemOther, m_vecFractManifElm, shiftToUnclosedFracts );
    1182              : 
    1183            0 :                 if( found && shiftToUnclosedFracts )
    1184              :                 {
    1185              :                         // for the case that a fracture is not closed at a vertex, shift the in principle
    1186              :                         // fracture vertex to the gerneral vertices, as useless for segmente construction
    1187              :                         // and useless for expansion
    1188              : 
    1189            0 :                         m_vecUnclosedFractManifElm.push_back(manifFractElemOther);
    1190              : 
    1191              : 
    1192              : //                      MANIFELM const & manifel = manifFractElemOther.getManifElm();
    1193              : //                      typename AttachedGenerManifElemInfo::PairLowEl const & pairLowEl = manifFractElemOther.getPairLowElm();
    1194              : //
    1195              : //                      AttachedGenerManifElemInfo agmei( manifel, pairLowEl );
    1196              : 
    1197              : //                      m_vecUnclosedFractManifElm.push_back(agmei);
    1198              :                 }
    1199              : 
    1200            0 :                 return found;
    1201              : 
    1202              :         }
    1203              : 
    1204              :         template <typename NOGEN>
    1205              :         bool const searchFractManifElem( NOGEN const & manifFractElemOther, bool shiftToGeneral ) = delete;
    1206              : 
    1207              :         bool const searchBndryManifElem( AttachedBndryManifElemInfo const & manifBndryElemOther )
    1208              :         {
    1209              :                 return searchManifElem( manifBndryElemOther, m_vecBndryManifElm, false );
    1210              :         }
    1211              : 
    1212              : //      bool const searchInnerSegmentManifElem( AttachedGenerManifElemInfo const & manifInnerSegmElemOther, bool eraseFound = true )
    1213              : //      {
    1214              : //              return searchManifElem( manifInnerSegmElemOther, m_vecInnerSegmentManifElm, eraseFound );
    1215              : //      }
    1216              : 
    1217              : //      bool const tryToTouchManifElem( AttachedFractManifElemInfo const & manifElemOther ) const
    1218              : //      {
    1219              : ////            bool managed2Touch = false;
    1220              : //
    1221              : //              for( typename VecAttachedFractManifElemInfo::iterator afeiIter  = m_vecFractManifElm.begin();
    1222              : //                                                                                                       afeiIter != m_vecFractManifElm.end();
    1223              : //                                                                                                       afeiIter++
    1224              : //              )
    1225              : //              {
    1226              : //                      AttachedFractManifElemInfo & manifElmTest = *afeiIter;
    1227              : //
    1228              : //                      if( manifElemOther.testIfEquals(manifElmTest) )
    1229              : //                      {
    1230              : //                              managed2Touch = true;
    1231              : //
    1232              : //                              m_vecFractManifElm.erase(afeiIter);
    1233              : //
    1234              : //                              return true;
    1235              : //                      }
    1236              : //              }
    1237              : //
    1238              : //              return false;
    1239              : //
    1240              : ////            return managed2Touch;
    1241              : //
    1242              : ////            for( auto & ameti : m_vecFractManifElmTouchInfo )
    1243              : ////            {
    1244              : ////                    AttachedFractManifElemInfo & manifElmTest = ameti.first;
    1245              : ////                    bool & alreadyTouched = ameti.second;
    1246              : ////
    1247              : ////                    if( ! alreadyTouched )
    1248              : ////                    {
    1249              : ////                            if( manifElemOther.testIfEquals( manifElmTest ) )
    1250              : ////                            {
    1251              : ////                                    alreadyTouched = true;
    1252              : ////                            }
    1253              : ////                    }
    1254              : ////
    1255              : ////                    if( alreadyTouched )
    1256              : ////                    {
    1257              : ////                            managed2Touch = true;
    1258              : ////                            break;
    1259              : ////                    }
    1260              : ////            }
    1261              : //
    1262              : //              return managed2Touch;
    1263              : //      }
    1264              : 
    1265              : //      VecAttachedFractManifElemInfo const getAlreadyTouchedManifElems() const
    1266              : //      {
    1267              : //              VecAttachedFractManifElemInfo alreadyTouchedManifElms;
    1268              : //
    1269              : //              for( const auto & ameti : m_vecFractManifElmTouchInfo )
    1270              : //              {
    1271              : //                      if( ameti.second )
    1272              : //                              alreadyTouchedManifElms.push_back( ameti );
    1273              : //              }
    1274              : //
    1275              : //              return alreadyTouchedManifElms;
    1276              : //      }
    1277              : 
    1278              : //      VecAttachedFractManifElemInfo const getSoFarUnTouchedManifElems() const
    1279              : //      {
    1280              : //              VecAttachedFractManifElemInfo unTouchedManifElms;
    1281              : //
    1282              : //              for( const auto & ameti : m_vecFractManifElmTouchInfo )
    1283              : //              {
    1284              : //                      if( ! ameti.second )
    1285              : //                              unTouchedManifElms.push_back( ameti );
    1286              : //              }
    1287              : //
    1288              : //              return unTouchedManifElms;
    1289              : //      }
    1290              : 
    1291              : //      bool const testIfAllSidesTouched() const
    1292              : //      {
    1293              : //              if( m_allSidesTouched )
    1294              : //                      return true;
    1295              : //
    1296              : //              bool allSidesTouched = true;
    1297              : //
    1298              : //              for( const auto & ameti : m_vecFractManifElmTouchInfo )
    1299              : //              {
    1300              : //                      if( ! ameti.second )
    1301              : //                      {
    1302              : //                              allSidesTouched = false;
    1303              : //                      }
    1304              : //              }
    1305              : //
    1306              : //              m_allSidesTouched = allSidesTouched;
    1307              : //
    1308              : //              return m_allSidesTouched;
    1309              : //      }
    1310              : 
    1311              : private:
    1312              : 
    1313              : //      bool m_allSidesTouched;
    1314              : 
    1315              :         FULLDIM_ELEM m_fullDimElm;
    1316              : 
    1317              :         bool m_elementMarked;
    1318              : 
    1319              :         VecAttachedFractManifElemInfo m_vecFractManifElm;
    1320              : 
    1321              :         VecAttachedFractManifElemInfo m_vecUnclosedFractManifElm;
    1322              : 
    1323              : 
    1324              : //      using AttFractManifElmTouchInf = std::pair<AttachedFractManifElemInfo,bool>;
    1325              : //      using VecAttFractManifElmTouchInf = std::vector<AttFractManifElmTouchInf>;
    1326              : //
    1327              : //      VecAttFractManifElmTouchInf m_vecFractManifElmTouchInfo;
    1328              : 
    1329              :         VecAttachedGenerManifElemInfo m_vecGenerManifElm;
    1330              : 
    1331              :         VecAttachedBndryManifElemInfo m_vecBndryManifElm;
    1332              : 
    1333              : //      VecAttachedGenerManifElemInfo m_vecInnerSegmentManifElm;
    1334              : 
    1335              : //      using AttGenerManifElmTouchInf = std::pair<AttachedGenerManifElemInfo,bool>;
    1336              : //      using VecAttGenerManifElmTouchInf = std::vector<AttGenerManifElmTouchInf>;
    1337              : //
    1338              : //      VecAttFractManifElmTouchInf m_vecGenerManifElmTouchInfo;
    1339              : 
    1340              : 
    1341              : //    template<
    1342              : ////    typename std::enable_if<std::is_same<FULLDIM_ELEM,Volume* const &>::value, true>,
    1343              : ////    typename std::enable_if<std::is_same<MANIFELM,Face* const &>::value, true>
    1344              : ////    typename std::enable_if<std::is_same<FULLDIM_ELEM,Volume* const &>::value, true>,
    1345              : //      typename std::enable_if<std::is_same<MANIFELM,Face* const &>::value,bool>
    1346              : //      >
    1347              :         //std::enable_if<std::is_same<MANIFELM,Face* const &>::value>
    1348              :         template
    1349              :         <
    1350              :         typename = std::enable_if<std::is_same<Volume*,FULLDIM_ELEM>::value>,
    1351              :         typename = std::enable_if<std::is_same<Face*,MANIFELM>::value>
    1352              : //      typename = std::enable_if<std::is_same<Volume* const &,FULLDIM_ELEM>::value>,
    1353              : //      typename = std::enable_if<std::is_same<Face* const &,MANIFELM>::value>
    1354              :         >
    1355            0 :         bool fullDimElmContainsManif( MANIFELM const & manifEl, Grid & grid )
    1356              :         {
    1357              : //              bool contained = false;
    1358              : 
    1359            0 :                 for( INDEX_TXP iFac = 0; iFac < m_fullDimElm->num_faces(); iFac++ )
    1360              :                 {
    1361              : 
    1362              : //                      static_assert(std::is_same<decltype(m_fullDimElm), Volume *>::value);
    1363              : 
    1364            0 :                         Face * fac = grid.get_face(m_fullDimElm,iFac);
    1365              : 
    1366            0 :                         if( fac == manifEl )
    1367              :                         {
    1368              :                                 return true;
    1369              : //                              contained = true;
    1370              : //                              break;
    1371              :                         }
    1372              :                 }
    1373              : 
    1374              : //              return contained;
    1375              :                 return false;
    1376              :         }
    1377              : 
    1378              : 
    1379              :         template <typename ATT_MANIF_ELM_INF >
    1380            0 :         bool const searchManifElem( ATT_MANIF_ELM_INF const & manifElemOther,
    1381              :                                                                 std::vector<ATT_MANIF_ELM_INF> & memVecManifElem,
    1382              :                                                                 bool eraseFound = true )
    1383              :         const
    1384              :         {
    1385              : 
    1386            0 :                 for( typename std::vector<ATT_MANIF_ELM_INF>::iterator afeiIter  = memVecManifElem.begin();
    1387            0 :                                                                                                                            afeiIter != memVecManifElem.end();
    1388              :                                                                                                                            afeiIter++
    1389              :                 )
    1390              :                 {
    1391              :                         ATT_MANIF_ELM_INF & manifElmTest = *afeiIter;
    1392              : 
    1393            0 :                         if( manifElemOther.testIfEquals(manifElmTest) )
    1394              :                         {
    1395              : 
    1396            0 :                                 if( eraseFound )
    1397              :                                         memVecManifElem.erase(afeiIter);
    1398              : 
    1399              :                                 return true;
    1400              :                         }
    1401              :                 }
    1402              : 
    1403              :                 return false;
    1404              :         }
    1405              : 
    1406              : 
    1407              : 
    1408              :         template <typename ATT_MANIF_ELM_INFO >
    1409            0 :         bool addManifElem( ATT_MANIF_ELM_INFO const & manifElm,
    1410              :                                            std::vector<ATT_MANIF_ELM_INFO> & memVecManifElm,
    1411              :                                            Grid & grid )
    1412              :         {
    1413              :                 // Caution: first test if manifold elem is at all part of the fulldim elem manifols
    1414              :                 // if not, return false directly
    1415              : 
    1416            0 :                 if( ! fullDimElmContainsManif( manifElm.getManifElm(), grid ) )
    1417              :                         return false;
    1418              : 
    1419              :                 // if manif elem is in principle part of the fulldim elem manifolds,
    1420              :                 // then we need to check if it is already integrated
    1421              : 
    1422            0 :                 for( auto const & me : memVecManifElm )
    1423              :                 {
    1424            0 :                         if( manifElm.testIfEquals(me) )
    1425              :                         {
    1426              :                                 return false;
    1427              :                         }
    1428              :                 }
    1429              : 
    1430              :                 // not contained so far, but part of the manifolds of the fulldim elem
    1431            0 :                 memVecManifElm.push_back(manifElm);
    1432              : 
    1433            0 :                 return true;
    1434              : 
    1435              :         }
    1436              : 
    1437              : 
    1438              : };
    1439              : 
    1440              : //////////////////////////////////////////////////////////////////
    1441              : 
    1442              : 
    1443              : // Ebenentyp: a x1 + b x2 + c x3 = rhs, normal * ( vecX - baseVect ) = 0
    1444              : template<typename VECTOR_TYP,
    1445              :                  typename LOWDIMELM
    1446              : >
    1447            0 : class ManifoldDescriptor
    1448              : {
    1449              : public:
    1450              : 
    1451              :         enum ManifoldType { isFracture, isBoundary, isArtificial };
    1452              : 
    1453              :         template<typename = std::enable_if<std::is_same<VECTOR_TYP,vector3>::value>>
    1454              : //                      ManifoldDescriptor( int sudo = -1, number scaleShiftNormal = 0 )
    1455            0 :         ManifoldDescriptor()
    1456              :         : m_normalVect(vector3()),
    1457              :           m_baseVect(vector3()),
    1458            0 :           m_rhs(0),
    1459            0 :           m_scaleShiftNormal(0),
    1460            0 :           m_dim(3),
    1461            0 :           m_sudo(-1),
    1462            0 :           m_manifTyp( isArtificial )
    1463              :         {
    1464              :         }
    1465              : 
    1466              : 
    1467              :         template<typename = std::enable_if<std::is_same<VECTOR_TYP,vector3>::value>>
    1468            0 :         ManifoldDescriptor( VECTOR_TYP const & normalVect,
    1469              :                                                 VECTOR_TYP const & baseVect,
    1470              :                                                 int sudo = -1,
    1471              :                                                 ManifoldType manifTyp = isArtificial,
    1472              :                                                 number scaleShiftNormal = 0
    1473              :                                                 )
    1474              :         : m_normalVect(normalVect),
    1475              :           m_baseVect(baseVect),
    1476            0 :           m_scaleShiftNormal(scaleShiftNormal),
    1477            0 :           m_dim(3),
    1478            0 :           m_sudo(sudo),
    1479            0 :           m_manifTyp( manifTyp ),
    1480              :           m_lowDimElms(std::vector<LOWDIMELM>())
    1481              :         {
    1482            0 :                 m_rhs = 0;
    1483              : 
    1484              :                 UG_LOG("Ebenenkoordinatenform ");
    1485              : 
    1486            0 :                 for( int i = 0; i < m_dim; i++ )
    1487              :                 {
    1488            0 :                         m_rhs += normalVect[i]*baseVect[i];
    1489              : 
    1490            0 :                         UG_LOG( " + " << normalVect[i] << " x_" << i << " " );
    1491              :                 }
    1492              : 
    1493            0 :                 UG_LOG(" = " << m_rhs << std::endl);
    1494              : 
    1495            0 :         }
    1496              : 
    1497            0 :         VECTOR_TYP const & spuckNormalVector() const { return m_normalVect; }
    1498            0 :         VECTOR_TYP const & spuckBaseVector() const { return m_baseVect; }
    1499              : 
    1500            0 :         int const spuckSudo() const { return m_sudo; }
    1501              : 
    1502            0 :         ManifoldType const spuckManifTyp() const { return m_manifTyp; }
    1503              : 
    1504              :         number const spuckScaleShiftNormal() const { return m_scaleShiftNormal; }
    1505              : 
    1506              :         void schluckSudo( int sudo ) { m_sudo = sudo; }
    1507              : 
    1508              :         void schluckManifTyp( ManifoldType manifTyp )  { m_manifTyp = manifTyp; }
    1509              : 
    1510              :         void schluckScaleShiftNormal( number scaleShiftNormal )
    1511              :         {
    1512            0 :                 m_scaleShiftNormal = scaleShiftNormal;
    1513              :         }
    1514              : 
    1515              :         number const & spuckRHS() const { return m_rhs; }
    1516              : 
    1517              :         template<typename = std::enable_if<    std::is_same<VECTOR_TYP,vector3>::value
    1518              : //                                                                              || std::is_same<VECTOR_TYP,vector2>::value>
    1519              :                                                                         >
    1520              :         >
    1521              :         bool spuckPlaneShiftedAlong( VECTOR_TYP const & shiftVec, ManifoldDescriptor & manifoldDescr )
    1522              :         {
    1523              :                 VECTOR_TYP shiftedBaseVect;
    1524              : //              number rhsShiftedPlane = 0;
    1525              : 
    1526              :                 VecAdd( shiftedBaseVect, m_baseVect, shiftVec );
    1527              : 
    1528              :                 UG_LOG("Ebenenkoordinatenform Shifted Plane " << std::endl);
    1529              : 
    1530              : //              ManifoldDescriptor( VECTOR_TYP const & normalVect,
    1531              : //                                                      VECTOR_TYP const & baseVect,
    1532              : //                                                      int sudo = -1,
    1533              : //                                                      ManifoldType = isArtificial,
    1534              : //                                                      number scaleShiftNormal = 0
    1535              : //                                                      )
    1536              : 
    1537              :                 manifoldDescr = ManifoldDescriptor( m_normalVect, shiftedBaseVect, m_sudo, m_manifTyp, 0 );
    1538              : 
    1539              :                 return true;
    1540              : 
    1541              :         }
    1542              : 
    1543              :         template<typename = std::enable_if<std::is_same<VECTOR_TYP,vector3>::value >>
    1544            0 :         bool spuckPlaneShifted( ManifoldDescriptor & manifoldDescr )
    1545              :         {
    1546              : 
    1547              :                 UG_LOG("Ebenenkoordinatenform Shifted Plane " << std::endl);
    1548              : 
    1549            0 :                 manifoldDescr = ManifoldDescriptor( m_normalVect, spuckShiftedBaseVect(), m_sudo, m_manifTyp, 0 );
    1550              : 
    1551            0 :                 if( ! manifoldDescr.schluckLowDimElms(m_lowDimElms) )
    1552              :                 {
    1553              :                         UG_LOG("Neuer Manifold Descripter verschoben ohne Ecken" << std::endl);
    1554              :                 }
    1555              : 
    1556            0 :                 return true;
    1557              : 
    1558              :         }
    1559              : 
    1560              : 
    1561              :         template<typename = std::enable_if< std::is_same<VECTOR_TYP,vector3>::value>>
    1562            0 :         VECTOR_TYP spuckShiftedBaseVect()
    1563              :         {
    1564              :                 VECTOR_TYP shiftVec;
    1565              : 
    1566            0 :                 VecScale(shiftVec, m_normalVect, m_scaleShiftNormal );
    1567              : 
    1568              :                 VECTOR_TYP shiftedBaseVec;
    1569              : 
    1570              :                 VecAdd( shiftedBaseVec, m_baseVect, shiftVec );
    1571              : 
    1572            0 :                 return shiftedBaseVec;
    1573              :         }
    1574              : 
    1575              :         bool schluckLowDimElms( std::vector<LOWDIMELM> const & lowDimElms )
    1576              :         {
    1577            0 :                 m_lowDimElms = lowDimElms;
    1578              :                 return ( m_lowDimElms.size() > 0 );
    1579              :         }
    1580              : 
    1581              :         bool const spuckLowDimElms( std::vector<LOWDIMELM> & lowDimElms ) const
    1582              :         {
    1583            0 :                 lowDimElms = m_lowDimElms;
    1584              :                 return ( m_lowDimElms.size() > 0 );
    1585              :         }
    1586              : 
    1587              : private:
    1588              : 
    1589              :         VECTOR_TYP m_normalVect;
    1590              :         VECTOR_TYP m_baseVect;
    1591              :         number m_rhs;
    1592              :         number m_scaleShiftNormal;
    1593              : 
    1594              :         // could be defined as static const variable, but then depending on the template parameter
    1595              :         // might be an idea for future, but no real use, but would be "nice" from the meta programmig point of view
    1596              :         int m_dim;
    1597              :         int m_sudo;
    1598              :         ManifoldType m_manifTyp;
    1599              : 
    1600              :         std::vector<LOWDIMELM> m_lowDimElms;
    1601              : };
    1602              : 
    1603              : 
    1604              : //////////////////////////////////////////////////////////////////
    1605              : 
    1606              : //// needs to be declared as members used in following class
    1607              : //template
    1608              : //<
    1609              : //typename FULLDIMEL,
    1610              : //typename MANIFEL,
    1611              : //typename LOWDIMEL,
    1612              : //typename VRTXTYP,
    1613              : //typename INDEXTYP
    1614              : //>
    1615              : //class EndingCrossingFractSegmentInfo;
    1616              : 
    1617              : //////////////////////////////////////////////////////////////
    1618              : 
    1619              : 
    1620              : template <
    1621              : typename FULLDIM_ELEM,
    1622              : typename MANIFELM,
    1623              : typename LOWDIMELM,
    1624              : typename INDEX_TXP,
    1625              : typename VECTOR_TYP,
    1626              : typename VRTXTYP
    1627              : >
    1628              : class SegmentSides
    1629              : {
    1630              : public:
    1631              : 
    1632              :         enum VrtxFracStatus { noFracSuDoAtt = 0,
    1633              :                                                   oneFracSuDoAtt = 1,
    1634              :                                                   twoFracSuDoAtt = 2,
    1635              :                                                   threeFracSuDoAtt = 3 };
    1636              : 
    1637              :         using AttFractElm = AttachedFractElem<MANIFELM, LOWDIMELM, INDEX_TXP, VECTOR_TYP>;
    1638              :         using AttBndryElm = AttachedBoundryElem<MANIFELM, LOWDIMELM, INDEX_TXP, VECTOR_TYP>;
    1639              : 
    1640              :         using VecAttFractElm = std::vector<AttFractElm>;
    1641              :         using VecAttBndryElm = std::vector<AttBndryElm>;
    1642              : 
    1643              :         using PairSudoNormlV = std::pair<INDEX_TXP,VECTOR_TYP>;
    1644              :         using VecPairSudoNormlV = std::vector<PairSudoNormlV>;
    1645              : 
    1646              :         using PairSudoVecLowDiEl = std::pair<INDEX_TXP, std::vector<LOWDIMELM> >;
    1647              :         using VecPairSudoVecLowDiEl = std::vector<PairSudoVecLowDiEl>;
    1648              : 
    1649              :         using ManifDescr = ManifoldDescriptor<VECTOR_TYP, LOWDIMELM>;
    1650              :         using VecManifDescr = std::vector<ManifDescr>;
    1651              : 
    1652              :         // TODO FIXME das soll gleich durch den Manifold Descriptor ersetzt werden
    1653              :         // oder eine Basisklasse von ihm, die nicht so viele Infos enthält
    1654              :         // aber mindestens NormalenVektor, Sudo, und ob Boundary oder Fracture
    1655              :         // kann auch vielleicht einfach eine Klasse sein, die noch einen Parameter enthält
    1656              :         // der sich abfragen lässt, auch als Template vielleicht, true false, fracture or not
    1657              :         // also was wie template < index, normal, bool > pairsudonormlbla, oder sowas.....
    1658              :         // oder man kann einen Parameter setzen für diese Klasse, die extern definiert wird......
    1659              :         // bool isFracture true false.....
    1660              : 
    1661              :         template<   typename = std::enable_if< std::is_pointer<LOWDIMELM>::value>
    1662              :                         >
    1663            0 :         SegmentSides( VRTXTYP const & vrt, bool isBndry = false )
    1664            0 :         : m_vrt(vrt),
    1665            0 :           m_shiftDirectionIfUnclosedFractPresent(nullptr),
    1666              :           m_vecAttFractElms(VecAttFractElm()),
    1667              :           m_vecAttUnclosedFractElms(VecAttFractElm()),
    1668              :           m_vecAttBndryElms(VecAttBndryElm()),
    1669              :           m_vecFractSudosNormlV(VecPairSudoNormlV()),
    1670              :           m_vecBndrySudosNormlV(VecPairSudoNormlV()),
    1671              :           m_vecFractSudoLowDiEl(VecPairSudoVecLowDiEl()),
    1672              :           m_vecBndrySudoLowDiEl(VecPairSudoVecLowDiEl()),
    1673            0 :           m_isBoundary(isBndry),
    1674            0 :           m_averaged(false),
    1675              :           m_contribFulldimElm(std::vector<FULLDIM_ELEM>()),
    1676            0 :           m_volEdgesDetermined(false),
    1677              :           m_vecVolEdges(std::vector<LOWDIMELM>())
    1678              :         {};
    1679              : 
    1680              : //      template<typename = std::enable_if< std::is_pointer<VRTXTYP>::value>>
    1681              : //      SegmentSides()
    1682              : //      : m_vrt(nullptr),
    1683              : //        m_vecAttFractElms(VecAttFractElm()),
    1684              : //        m_vecAttUnclosedFractElms(VecAttFractElm()),
    1685              : //        m_vecAttBndryElms(VecAttBndryElm()),
    1686              : //        m_vecFractSudosNormlV(VecPairSudoNormlV()),
    1687              : //        m_vecBndrySudosNormlV(VecPairSudoNormlV()),
    1688              : //        m_isBoundary(false),
    1689              : //        m_averaged(false),
    1690              : //        m_contribFulldimElm(std::vector<FULLDIM_ELEM>())
    1691              : //      {};
    1692              : 
    1693              : 
    1694            0 :         bool const isBoundary() const { return m_isBoundary; }
    1695              : 
    1696              :         VRTXTYP const spuckVertex() const
    1697              :         {
    1698            0 :                 return m_vrt;
    1699              :         }
    1700              : 
    1701              :         bool schluckFulldimElem( FULLDIM_ELEM const & fudielm )
    1702              :         {
    1703            0 :                 m_volEdgesDetermined = false;
    1704            0 :                 return addElem(m_contribFulldimElm, fudielm);
    1705              : //              m_contribFulldimElm.push_back(fudielm);
    1706              :         }
    1707              : 
    1708              :         bool const spuckVecFulldimElem( std::vector<FULLDIM_ELEM> & fudielm ) const
    1709              :         {
    1710            0 :                 fudielm = m_contribFulldimElm;
    1711              : 
    1712              :                 return ( m_contribFulldimElm.size() != 0 );
    1713              :         }
    1714              : 
    1715              :         template< //typename GRID,
    1716              :                           //typename = std::enable_if< std::is_same<GRID, Grid >::value>,
    1717              :                           typename = std::enable_if< std::is_same<FULLDIM_ELEM,Volume*>::value>,
    1718              :                           typename = std::enable_if< std::is_same<FULLDIM_ELEM,Volume*>::value>
    1719              :                         >
    1720              :         bool spuckListLowdimElmsOfVols( std::vector<LOWDIMELM> & listLowdimElms, Grid & grid )
    1721              :         {
    1722            0 :                 if( ! m_volEdgesDetermined )
    1723              :                 {
    1724            0 :                         determineListLowdimElms( grid );
    1725              :                 }
    1726              : 
    1727            0 :                 listLowdimElms = m_vecVolEdges;
    1728              : 
    1729            0 :                 return m_volEdgesDetermined;
    1730              :         }
    1731              : 
    1732              : 
    1733              :         VrtxFracStatus const spuckCrossingTyp() const
    1734              :         {
    1735            0 :                 VrtxFracStatus vfsFract =  static_cast<VrtxFracStatus>(m_vecFractSudosNormlV.size());
    1736              : 
    1737            0 :                 if( m_isBoundary )
    1738              :                 {
    1739              :                         VrtxFracStatus vfsBndry = static_cast<VrtxFracStatus>(m_vecBndrySudosNormlV.size());
    1740              : 
    1741            0 :                         return static_cast<VrtxFracStatus>( static_cast<INDEX_TXP>(vfsFract) + static_cast<INDEX_TXP>(vfsBndry) );
    1742              :                 }
    1743              : 
    1744              :                 return vfsFract;
    1745              :         }
    1746              : 
    1747              :         bool schluckVecAttFractElm( std::vector<AttFractElm> const & vecAtFracEl )
    1748              :         {
    1749            0 :                 return schluckVecAttElm( vecAtFracEl, m_vecAttFractElms );
    1750              :         }
    1751              : 
    1752              :         template< typename NOFRACT >
    1753              :         bool schluckVecAttFractElm( std::vector<NOFRACT> const & vecAtFracEl ) = delete;
    1754              : 
    1755              :         bool schluckAttFractElm( AttFractElm const & afeNew )
    1756              :         {
    1757              :                 return schluckAttElm( afeNew, m_vecAttFractElms );
    1758              : 
    1759              : //              if( ! isStillUnknown( afeNew, m_vecAttFractElms ) )
    1760              : //              {
    1761              : //                      return false;
    1762              : //              }
    1763              : //
    1764              : //              m_vecAttFractElms.push_back(afeNew);
    1765              : //
    1766              : //              return true;
    1767              :         }
    1768              : 
    1769              :         template< typename NOFRACT >
    1770              :         bool schluckAttFractElm( NOFRACT const & afeNew ) = delete;
    1771              : 
    1772              :         // soll auch in der Lage sein, die einzenlen Fracture faces wieder aus zu spucken als Liste
    1773              :         // analog auch dan      ach die boundary Geschichten
    1774              :         bool const spuckVecAttFractElm( std::vector<AttFractElm> & vecAttFracEl ) const
    1775              :         {
    1776            0 :                 vecAttFracEl = m_vecAttFractElms;
    1777              :                 return true;
    1778              :         }
    1779              : 
    1780              :         bool schluckVecAttBndryElm( std::vector<AttBndryElm> const & vecAtBndryEl )
    1781              :         {
    1782              : //              if( ! checkIfIsAtBndry() )
    1783              : //                      return false;
    1784              : 
    1785            0 :                 return schluckVecAttElm( vecAtBndryEl, m_vecAttBndryElms );
    1786              :         }
    1787              : 
    1788              :         bool schluckAttBndryElm( AttBndryElm const & afeNew )
    1789              :         {
    1790              : //              if( ! checkIfIsAtBndry() )
    1791              : //                      return false;
    1792              : 
    1793              :                 return schluckAttElm( afeNew, m_vecAttBndryElms );
    1794              : 
    1795              : //              if( ! isStillUnknown( afeNew, m_vecAttBndryElms ) )
    1796              : //              {
    1797              : //                      return false;
    1798              : //              }
    1799              : //
    1800              : //              m_vecAttBndryElms.push_back(afeNew);
    1801              : //
    1802              : //              return true;
    1803              :         }
    1804              : 
    1805              :         bool spuckVecAttBndryElm( std::vector<AttBndryElm> & vecAtBndryEl )
    1806              :         {
    1807              :                 vecAtBndryEl = m_vecAttBndryElms;
    1808              :                 return true;
    1809              :         }
    1810              : 
    1811              : 
    1812              :         bool schluckVecAttUnclosedFractElm( std::vector<AttFractElm> const & vecAtFracEl )
    1813              :         {
    1814            0 :                 return schluckVecAttElm( vecAtFracEl, m_vecAttUnclosedFractElms, true );
    1815              :         }
    1816              : 
    1817              :         template< typename NOFRACT >
    1818              :         bool schluckVecAttUnclosedFractElm( std::vector<NOFRACT> const & vecAtFracEl ) = delete;
    1819              : 
    1820              :         bool schluckAttUnclosedFractElm( AttFractElm const & afeNew )
    1821              :         {
    1822              :                 return schluckAttElm( afeNew, m_vecAttUnclosedFractElms, true );
    1823              :         }
    1824              : 
    1825              :         template< typename NOFRACT >
    1826              :         bool schluckAttUnclosedFractElm( NOFRACT const & afeNew ) = delete;
    1827              : 
    1828              :         bool const spuckVecAttUnclosedFractElm( std::vector<AttFractElm> & vecAttFracEl ) const
    1829              :         {
    1830            0 :                 vecAttFracEl = m_vecAttUnclosedFractElms;
    1831              :                 return true;
    1832              :         }
    1833              : 
    1834              :         bool const hasUnclosedFaces() const
    1835              :         {
    1836              :                 return ( m_vecAttUnclosedFractElms.size() > 0 );
    1837              :         }
    1838              : 
    1839              :         template<   typename = std::enable_if< std::is_pointer<LOWDIMELM>::value>
    1840              :                         >
    1841            0 :         bool schluckLowdimElmShiftDirectionIfUnclosedFractPresent( LOWDIMELM const & shiftDirectionElm )
    1842              :         {
    1843            0 :                 if(    m_shiftDirectionIfUnclosedFractPresent != nullptr
    1844            0 :                         && shiftDirectionElm != m_shiftDirectionIfUnclosedFractPresent
    1845              :                   )
    1846              :                 {
    1847              :                         UG_LOG("Shift direction already set different " << std::endl);
    1848            0 :                         UG_THROW("Shift direction already set different " << std::endl);
    1849              :                 }
    1850              : 
    1851            0 :                 if( shiftDirectionElm != nullptr )
    1852              :                 {
    1853            0 :                         m_shiftDirectionIfUnclosedFractPresent = shiftDirectionElm;
    1854            0 :                         return true;
    1855              :                 }
    1856              : 
    1857              :                 return false;
    1858              :         }
    1859              : 
    1860              :         template<   typename = std::enable_if< std::is_pointer<LOWDIMELM>::value>
    1861              :                         >
    1862              :         bool const spuckLowdimElmShiftDirectionIfUnclosedFractPresent( LOWDIMELM & shiftDirectionElm ) const
    1863              :         {
    1864            0 :                 if( m_shiftDirectionIfUnclosedFractPresent != nullptr )
    1865              :                 {
    1866            0 :                         shiftDirectionElm = m_shiftDirectionIfUnclosedFractPresent;
    1867            0 :                         return true;
    1868              :                 }
    1869              : 
    1870              :                 return false;
    1871              :         }
    1872              : 
    1873            0 :         bool averageAll()
    1874              :         {
    1875            0 :                 if( m_isBoundary )
    1876              :                 {
    1877            0 :                         if( ! averageBndryNormals() )
    1878              :                                 return false;
    1879              :                 }
    1880              : 
    1881            0 :                 if( ! averageFractNormals() )
    1882              :                         return false;
    1883              : 
    1884            0 :                 m_averaged = true;
    1885              : 
    1886            0 :                 return m_averaged;
    1887              :         }
    1888              : 
    1889              :         bool const spuckFractSudoNormls( VecPairSudoNormlV & vecFractSudosNormlV ) const
    1890              :         {
    1891              :                 if( ! m_averaged )
    1892              :                 {
    1893              :                         UG_LOG("please average " << std::endl);
    1894              :                         UG_THROW("please average " << std::endl);
    1895              :                         return false;
    1896              :                 }
    1897              : 
    1898              :                 vecFractSudosNormlV = m_vecFractSudosNormlV;
    1899              : 
    1900              :                 return true;
    1901              :         }
    1902              : 
    1903              :         template<typename = std::enable_if< std::is_same<VECTOR_TYP,vector3>::value>>
    1904              :         bool const spuckFractManifDescr( VecManifDescr & vecManifDesc,
    1905              :                                                                          Grid::VertexAttachmentAccessor<APosition> const & aaPos,
    1906              :                                                                          bool clearDescVec = true
    1907              :         ) const
    1908              :         {
    1909            0 :                 return spuckManifDescr<ManifDescr::ManifoldType::isFracture>( vecManifDesc, aaPos, m_vecFractSudosNormlV, m_vecFractSudoLowDiEl, clearDescVec );
    1910              : //              return spuckManifDescr<0>( vecManifDesc, aaPos, m_vecFractSudosNormlV );
    1911              :         }
    1912              : 
    1913              : 
    1914              : 
    1915              : 
    1916              : //      bool spuckFractManifDescr( VecManifDescr & vecManifDesc, Grid::VertexAttachmentAccessor<APosition> const & aaPos )
    1917              : //      {
    1918              : //              if( ! m_averaged )
    1919              : //              {
    1920              : //                      UG_LOG("please average " << std::endl);
    1921              : //                      UG_THROW("please average " << std::endl);
    1922              : //                      return false;
    1923              : //              }
    1924              : //
    1925              : //              VecPairSudoNormlV const & vecFractSudosNormlV = m_vecFractSudosNormlV;
    1926              : //
    1927              : //              vecManifDesc.clear();
    1928              : //
    1929              : //              for( PairSudoNormlV const & psn : vecFractSudosNormlV )
    1930              : //              {
    1931              : //                      VECTOR_TYP posVrt = aaPos[m_vrt];
    1932              : //
    1933              : //                      int sudo = psn.first;
    1934              : //                      VECTOR_TYP normlVec = psn.second;
    1935              : //
    1936              : ////                    ManifoldDescriptor( VECTOR_TYP const & normalVect,
    1937              : ////                                                            VECTOR_TYP const & baseVect,
    1938              : ////                                                            int sudo = -1,
    1939              : ////                                                            ManifoldType = isArtificial,
    1940              : ////                                                            number scaleShiftNormal = 0
    1941              : ////                                                            )
    1942              : ////
    1943              : //
    1944              : //                      ManifDescr manifDesc( normlVec, posVrt, sudo, ManifDescr::ManifoldType::isFracture );
    1945              : //
    1946              : //                      vecManifDesc.push_back( manifDesc );
    1947              : //              }
    1948              : //
    1949              : //              return true;
    1950              : //      }
    1951              : 
    1952              :         bool spuckBndrySudoNormls( VecPairSudoNormlV & vecBndrySudosNormlV )
    1953              :         {
    1954              : //              if( ! checkIfIsAtBndry() )
    1955              : //                      return false;
    1956              : 
    1957              :                 if( ! m_averaged )
    1958              :                 {
    1959              :                         UG_LOG("please average " << std::endl);
    1960              :                         UG_THROW("please average " << std::endl);
    1961              :                         return false;
    1962              :                 }
    1963              : 
    1964              :                 vecBndrySudosNormlV = m_vecBndrySudosNormlV;
    1965              : 
    1966              :                 return true;
    1967              :         }
    1968              : 
    1969              :         template<typename = std::enable_if< std::is_same<VECTOR_TYP,vector3>::value>>
    1970              :         bool const spuckBndryManifDescr( VecManifDescr & vecManifDesc,
    1971              :                                                                          Grid::VertexAttachmentAccessor<APosition> const & aaPos,
    1972              :                                                                          bool clearDescVec = true
    1973              :         ) const
    1974              :         {
    1975            0 :                 return spuckManifDescr<ManifDescr::ManifoldType::isBoundary>( vecManifDesc, aaPos, m_vecBndrySudosNormlV, m_vecBndrySudoLowDiEl, clearDescVec );
    1976              :                 //              return spuckManifDescr<2>( vecManifDesc, aaPos, m_vecFractSudosNormlV );
    1977              :         }
    1978              : 
    1979              : 
    1980              : private:
    1981              : 
    1982              :         VRTXTYP m_vrt;
    1983              : 
    1984              :         LOWDIMELM m_shiftDirectionIfUnclosedFractPresent;
    1985              : 
    1986              :         VecAttFractElm m_vecAttFractElms;
    1987              :         VecAttFractElm m_vecAttUnclosedFractElms;
    1988              : 
    1989              :         VecAttBndryElm m_vecAttBndryElms;
    1990              : 
    1991              : 
    1992              : 
    1993              :         VecPairSudoNormlV m_vecFractSudosNormlV;
    1994              :         VecPairSudoNormlV m_vecBndrySudosNormlV;
    1995              : 
    1996              :         VecPairSudoVecLowDiEl m_vecFractSudoLowDiEl;
    1997              :         VecPairSudoVecLowDiEl m_vecBndrySudoLowDiEl;
    1998              : 
    1999              : 
    2000              :         bool m_isBoundary;
    2001              :         bool m_averaged;
    2002              : 
    2003              :         std::vector<FULLDIM_ELEM> m_contribFulldimElm;
    2004              : 
    2005              :         bool m_volEdgesDetermined;
    2006              :         std::vector<LOWDIMELM> m_vecVolEdges;
    2007              : 
    2008              :         // zu heikel, weil dabei Änderungen nicht übernommen würden, es sei denn, es wäre pointer, aber die
    2009              :         // wollen wir auch vermeiden
    2010              : //      EndingCrossingFractSegmentInfo<FULLDIM_ELEM, MANIFELM, LOWDIMELM, VRTXTYP, INDEX_TXP> m_endingCrossFractSegmInf;
    2011              : 
    2012              :         template <typename ATT_ELM, typename VEC_ATT_ELM,
    2013              :                           typename = std::enable_if<std::is_same<std::vector<ATT_ELM>,VEC_ATT_ELM>::value>,
    2014              :                           typename      = std::enable_if<std::is_base_of<AttFractElm,ATT_ELM>::value>
    2015              :                         >
    2016            0 :         bool isStillUnknown( ATT_ELM const & afeNew, VEC_ATT_ELM const & vecAttELm, bool acceptUnknowns = false )
    2017              :         {
    2018            0 :                 for( ATT_ELM const & afeAlt : vecAttELm )
    2019              :                 {
    2020              :                         if( afeAlt.testIfEquals(afeNew) )
    2021              :                         {
    2022              :                                 UG_LOG("Strange, already known?" << std::endl);
    2023            0 :                                 if( ! acceptUnknowns )
    2024            0 :                                         UG_THROW("Strange, already known?" << std::endl);
    2025              :                                 return false;
    2026              :                         }
    2027              :                 }
    2028              : 
    2029              :                 return true;
    2030              : 
    2031              :         }
    2032              : 
    2033              :         template <typename ATT_ELM,
    2034              :                           typename = std::enable_if<std::is_base_of<AttFractElm,ATT_ELM>::value>
    2035              :                         >
    2036            0 :         bool extractSudoList( std::vector<INDEX_TXP> & sudoListSegment, std::vector<ATT_ELM> const & vecAttELm )
    2037              :         {
    2038            0 :                 for( AttFractElm const & me : vecAttELm )
    2039              :                 {
    2040            0 :                         INDEX_TXP sudoNeeded = me.getSudo();
    2041              : 
    2042              :                         bool sudoIsKnown = false;
    2043              : 
    2044            0 :                         for( INDEX_TXP sudoInList : sudoListSegment )
    2045              :                         {
    2046            0 :                                 if( sudoInList == sudoNeeded )
    2047              :                                 {
    2048              :                                         sudoIsKnown = true;
    2049              :                                         break;
    2050              :                                 }
    2051              :                         }
    2052              : 
    2053            0 :                         if( ! sudoIsKnown )
    2054            0 :                                 sudoListSegment.push_back(sudoNeeded);
    2055              :                 }
    2056              : 
    2057            0 :                 return true;
    2058              :         }
    2059              : 
    2060              :         template <typename ATT_ELM,
    2061              :                           typename = std::enable_if<std::is_base_of<AttFractElm,ATT_ELM>::value>
    2062              :                         >
    2063            0 :         bool averageNormlForEachSudo( std::vector<ATT_ELM> const & vecAttElm, VecPairSudoNormlV & vecPSudoNrml, VecPairSudoVecLowDiEl & vecPSudoVecLowDiElm )
    2064              :         {
    2065              :                 // first determine appearing sudos
    2066              : 
    2067              :                 std::vector<INDEX_TXP> sudoListSegment;
    2068              : 
    2069            0 :                 extractSudoList(sudoListSegment,vecAttElm);
    2070              : 
    2071            0 :                 for( INDEX_TXP sudo : sudoListSegment )
    2072              :                 {
    2073              :                         VECTOR_TYP normlAvrg;
    2074              : 
    2075            0 :                         if( ! averageNormalForSpecificSudo( sudo, vecAttElm, normlAvrg ) )
    2076            0 :                                 return false;
    2077              : 
    2078              :                         std::pair<INDEX_TXP, VECTOR_TYP> sudoNorml( sudo, normlAvrg );
    2079              : 
    2080            0 :                         vecPSudoNrml.push_back(sudoNorml);
    2081              : 
    2082              :                         // TODO FIXME auch Liste mit Sudo plus Ecken, die auf der Mannigfaltigkeit liegen!!!!
    2083              : 
    2084              :                         std::vector<LOWDIMELM> vecLowDimElmsSudo;
    2085              : 
    2086            0 :                         if( ! extractLowDimElemsForSpecificSudo( sudo, vecAttElm, vecLowDimElmsSudo ) )
    2087              :                                 return false;
    2088              : 
    2089              :                         PairSudoVecLowDiEl sudoLDE( sudo, vecLowDimElmsSudo );
    2090              : 
    2091            0 :                         vecPSudoVecLowDiElm.push_back( sudoLDE );
    2092              : 
    2093              :                 }
    2094              : 
    2095              :                 return true;
    2096            0 :         }
    2097              : 
    2098              :         template <typename ATT_ELM,
    2099              :                           typename = std::enable_if<std::is_base_of<AttFractElm,ATT_ELM>::value>
    2100              :                         >
    2101            0 :         bool averageNormalForSpecificSudo( INDEX_TXP specfcSudo, std::vector<ATT_ELM> const & vecAttElm, VECTOR_TYP & normlAvrg )
    2102              :         {
    2103              :                 VECTOR_TYP normsSum(0,0,0);
    2104              :                 INDEX_TXP numContrNrmls = 0;
    2105              : 
    2106            0 :                 for( ATT_ELM const & ae : vecAttElm )
    2107              :                 {
    2108              :                         INDEX_TXP sudoElm = ae.getSudo();
    2109              : 
    2110            0 :                         if( specfcSudo == sudoElm )
    2111              :                         {
    2112              :                                 VECTOR_TYP normElm = ae.getNormalVec();
    2113              : 
    2114              :                                 VECTOR_TYP tmpSum = normsSum;
    2115              : 
    2116              :                                 VecAdd( normsSum, normElm, tmpSum );
    2117              : 
    2118            0 :                                 numContrNrmls++;
    2119              :                         }
    2120              :                 }
    2121              : 
    2122            0 :                 if( numContrNrmls == 0 )
    2123              :                 {
    2124              :                         UG_LOG("Kein Beitrag in SUdo? " << std::endl);
    2125            0 :                         UG_THROW("Kein Beitrag in SUdo? " << std::endl);
    2126              :                         return false;
    2127              :                 }
    2128              : 
    2129            0 :                 VecScale( normlAvrg, normsSum, 1. / static_cast<number>(numContrNrmls) );
    2130              : 
    2131              :                 return true;
    2132              : 
    2133              :         }
    2134              : 
    2135              :         template <typename ATT_ELM,
    2136              :                           typename = std::enable_if<std::is_base_of<AttFractElm,ATT_ELM>::value>
    2137              :                         >
    2138            0 :         bool extractLowDimElemsForSpecificSudo( INDEX_TXP specfcSudo, std::vector<ATT_ELM> const & vecAttElm, std::vector<LOWDIMELM> & vecLowDimElms )
    2139              :         {
    2140            0 :                 for( ATT_ELM const & ae : vecAttElm )
    2141              :                 {
    2142              :                         INDEX_TXP sudoElm = ae.getSudo();
    2143              : 
    2144            0 :                         if( specfcSudo == sudoElm )
    2145              :                         {
    2146              :                                 std::pair<LOWDIMELM,LOWDIMELM> paLoDiEl = ae.getPairLowElm();
    2147              : 
    2148            0 :                                 addElem(vecLowDimElms, paLoDiEl.first);
    2149            0 :                                 addElem(vecLowDimElms, paLoDiEl.second);
    2150              :                         }
    2151              : 
    2152              :                 }
    2153              : 
    2154            0 :                 return true;
    2155              :         }
    2156              : 
    2157              : 
    2158              :         bool averageFractNormals()
    2159              :         {
    2160            0 :                 return averageNormlForEachSudo( m_vecAttFractElms, m_vecFractSudosNormlV, m_vecFractSudoLowDiEl );
    2161              :         }
    2162              : 
    2163            0 :         bool averageBndryNormals()
    2164              :         {
    2165            0 :                 if( m_isBoundary )
    2166              :                 {
    2167            0 :                         return averageNormlForEachSudo( m_vecAttBndryElms, m_vecBndrySudosNormlV, m_vecBndrySudoLowDiEl );
    2168              :                 }
    2169              :                 else
    2170              :                 {
    2171              :                         UG_LOG("no boundary, no averaging");
    2172            0 :                         return false;
    2173              :                 }
    2174              :         }
    2175              : 
    2176              :         template
    2177              :         < typename ATT_ELM,
    2178              :           typename = std::enable_if<std::is_base_of<AttFractElm,ATT_ELM>::value>
    2179              :         >
    2180            0 :         bool schluckVecAttElm( std::vector<ATT_ELM> const & vecAttElNew, std::vector<ATT_ELM> & vecAttElmKnown, bool acceptUnknowns = false )
    2181              :         {
    2182              :                 bool allUnknown = true;
    2183              : 
    2184            0 :                 for( ATT_ELM const & aeN : vecAttElNew )
    2185              :                 {
    2186            0 :                         if( ! schluckAttElm( aeN, vecAttElmKnown, acceptUnknowns ) )
    2187              :                         {
    2188              :                                 allUnknown = false;
    2189              :                                 UG_LOG("ist schon bekannt" << std::endl);
    2190            0 :                                 if( ! acceptUnknowns)
    2191            0 :                                         UG_THROW("ist schon bekannt" << std::endl);
    2192              :                                 //return false;
    2193              :                         }
    2194              :                 }
    2195              : 
    2196            0 :                 return allUnknown;
    2197              :         }
    2198              : 
    2199              :         template
    2200              :         < typename ATT_ELM,
    2201              :           typename = std::enable_if<std::is_base_of<AttFractElm,ATT_ELM>::value>
    2202              :         >
    2203            0 :         bool schluckAttElm( ATT_ELM const & attElNew, std::vector<ATT_ELM> & vecAttElmKnown, bool acceptUnknowns = false )
    2204              :         {
    2205            0 :                 m_averaged = false;
    2206              : 
    2207            0 :                 if( ! isStillUnknown( attElNew, vecAttElmKnown, acceptUnknowns ) )
    2208              :                 {
    2209              :                         UG_LOG("ist schon bekannt" << std::endl);
    2210            0 :                         if( ! acceptUnknowns )
    2211            0 :                                 UG_THROW("ist schon bekannt" << std::endl);
    2212              :                         return false;
    2213              :                 }
    2214              : 
    2215            0 :                 vecAttElmKnown.push_back(attElNew);
    2216              : 
    2217            0 :                 return true;
    2218              :         }
    2219              : 
    2220              :         bool checkIfIsAtBndry()
    2221              :         {
    2222              :                 if( ! m_isBoundary )
    2223              :                 {
    2224              :                         UG_LOG("gibts keine Bndry " << std::endl);
    2225              :                         UG_THROW("gibts keine Bndry " << std::endl);
    2226              :                         return false;
    2227              :                 }
    2228              : 
    2229              :                 return m_isBoundary;
    2230              :         }
    2231              : 
    2232              : //      template<ManifDescr::ManifoldType manifTyp,
    2233              : //      template<typename ManifDescr::ManifoldType manifTyp,
    2234              :         template<typename ManifDescr::ManifoldType manifTyp,
    2235              :                          typename = std::enable_if< std::is_same<VECTOR_TYP,vector3>::value>
    2236              :                         >
    2237            0 :         bool const spuckManifDescr( VecManifDescr & vecManifDesc,
    2238              :                                                                 Grid::VertexAttachmentAccessor<APosition> const & aaPos,
    2239              :                                                                 VecPairSudoNormlV const & vecFractSudosNormlV,
    2240              :                                                                 VecPairSudoVecLowDiEl const & vecFractSudosLDE,
    2241              :                                                                 bool clearDescVec = true
    2242              :         ) const
    2243              :         {
    2244            0 :                 if( ! m_averaged )
    2245              :                 {
    2246              :                         UG_LOG("please average " << std::endl);
    2247            0 :                         UG_THROW("please average " << std::endl);
    2248              :                         return false;
    2249              :                 }
    2250              : 
    2251            0 :                 if( clearDescVec )
    2252              :                         vecManifDesc.clear();
    2253              : 
    2254            0 :                 for( PairSudoNormlV const & psn : vecFractSudosNormlV )
    2255              :                 {
    2256            0 :                         VECTOR_TYP posVrt = aaPos[m_vrt];
    2257              : 
    2258            0 :                         int sudo = psn.first;
    2259              :                         VECTOR_TYP normlVec = psn.second;
    2260              : 
    2261              : //                      ManifoldDescriptor( VECTOR_TYP const & normalVect,
    2262              : //                                                              VECTOR_TYP const & baseVect,
    2263              : //                                                              int sudo = -1,
    2264              : //                                                              ManifoldType = isArtificial,
    2265              : //                                                              number scaleShiftNormal = 0
    2266              : //                                                              )
    2267              : //
    2268              : 
    2269            0 :                         UG_LOG("ASSIGN MANIF TYP " << manifTyp << std::endl);
    2270            0 :                         ManifDescr manifDesc( normlVec, posVrt, sudo, manifTyp );
    2271              :                         // TODO FIXME der Manifold Descriptor muss noch die Vertizes wissen, die ihn aufspannen
    2272              :                         // abgesehen vom Zentrums-Vertex
    2273              : 
    2274            0 :                         if( ! addLowDimElmListForSudo( manifDesc, sudo, vecFractSudosLDE ) )
    2275              :                         {
    2276              :                                 UG_LOG("No low dim elems " << std::endl);
    2277            0 :                                 UG_THROW("No low dim elems " << std::endl);
    2278              :                                 return false;
    2279              :                         }
    2280              : 
    2281            0 :                         vecManifDesc.push_back( manifDesc );
    2282              :                 }
    2283              : 
    2284              :                 return true;
    2285              :         }
    2286              : 
    2287            0 :         bool const addLowDimElmListForSudo( ManifDescr & md, INDEX_TXP sudo, VecPairSudoVecLowDiEl const & vecFractSudosLDE ) const
    2288              :         {
    2289              :                 INDEX_TXP foundSudo = 0;
    2290              : 
    2291            0 :                 for( PairSudoVecLowDiEl const & psvlde : vecFractSudosLDE )
    2292              :                 {
    2293            0 :                         INDEX_TXP sudoFract = psvlde.first;
    2294              : 
    2295            0 :                         if( sudoFract == sudo )
    2296              :                         {
    2297            0 :                                 foundSudo++;
    2298              : 
    2299            0 :                                 std::vector<LOWDIMELM> const & vecLoDiEl = psvlde.second;
    2300              : 
    2301            0 :                                 if( ! md.schluckLowDimElms( vecLoDiEl ) )
    2302              :                                 {
    2303              :                                         UG_LOG("NO LOWDIM ELEMS" << std::endl);
    2304              :                                         return false;
    2305              :                                 }
    2306              :                         }
    2307              :                 }
    2308              : 
    2309            0 :                 if( foundSudo != 1 )
    2310              :                 {
    2311              :                         UG_LOG("NO SUDO FOUND LDE" << std::endl);
    2312              :                 }
    2313              : 
    2314            0 :                 return ( foundSudo == 1 );
    2315              :         }
    2316              : 
    2317              :         template< //typename GRID,
    2318              :                           //typename = std::enable_if< std::is_same<GRID, Grid >::value>,
    2319              :                           typename = std::enable_if< std::is_same<FULLDIM_ELEM,Volume*>::value>,
    2320              :                           typename = std::enable_if< std::is_same<FULLDIM_ELEM,Volume*>::value>
    2321              :                         >
    2322            0 :         void determineListLowdimElms( Grid & grid )
    2323              :         {
    2324            0 :                 for( FULLDIM_ELEM const & fe : m_contribFulldimElm )
    2325              :                 {
    2326            0 :                         for(size_t i_edge = 0; i_edge < fe->num_edges(); ++i_edge)
    2327              :                         {
    2328            0 :                                 LOWDIMELM lowDimElm = grid.get_edge( fe, i_edge );
    2329              : 
    2330            0 :                                 if( EdgeContains(lowDimElm, m_vrt))
    2331              :                                 {
    2332            0 :                                         addElem(m_vecVolEdges, lowDimElm);
    2333              :                                 }
    2334              :                         }
    2335              : 
    2336              :                 }
    2337              : 
    2338            0 :                 m_volEdgesDetermined = true;
    2339            0 :         }
    2340              : 
    2341              : 
    2342              : };
    2343              : 
    2344              : //////////////////////////////////////////////////////////////////
    2345              : 
    2346              : 
    2347              : 
    2348              : #if 0
    2349              : template <typename VEC_AVEI, typename OPERATION, typename INDX_TYP  >
    2350              : bool switchFulldimInfo( VEC_AVEI & vecAttVolElemInfoCop,
    2351              :                                             VEC_AVEI const & vecAttVolElemInfo,
    2352              :                                             VEC_AVEI & segmentAVEI,
    2353              :                                             OPERATION opera,
    2354              :                                                 INDX_TYP switchInd = 0
    2355              :                                          )
    2356              : {
    2357              :         auto & startVolInfoThisSegment = vecAttVolElemInfoCop[switchInd];
    2358              : 
    2359              :         auto const & startVol = startVolInfoThisSegment.opera();
    2360              : 
    2361              :         for( auto & possibleOrigVolInfo : vecAttVolElemInfo )
    2362              :         {
    2363              :                 auto const & possVol = possibleOrigVolInfo.opera();
    2364              : 
    2365              :                 if( possVol == startVol )
    2366              :                 {
    2367              :                         segmentAVEI().push_back(possibleOrigVolInfo);
    2368              :                         break;
    2369              :                 }
    2370              :         }
    2371              : 
    2372              :         if( segmentAVEI().size() != 1 )
    2373              :         {
    2374              :                 UG_LOG("No start volume reconstructible " << std::endl);
    2375              :                 UG_THROW("No start volume reconstructible " << std::endl);
    2376              :                 return false;
    2377              :         }
    2378              : 
    2379              :         if( ! vecAttVolElemInfoCop.erase( vecAttVolElemInfoCop.begin() + switchInd ) )
    2380              :                 return false;
    2381              : 
    2382              :         return true;
    2383              : 
    2384              : }
    2385              : #endif
    2386              : 
    2387              : 
    2388              : //////////////////////////////////////////////////////////////////////////
    2389              : 
    2390              : template
    2391              : <
    2392              : typename FULLDIMEL,
    2393              : typename MANIFEL,
    2394              : typename LOWDIMEL,
    2395              : typename VRTXTYP,
    2396              : typename INDEXTYP
    2397              : >
    2398              : class EndingCrossingFractSegmentInfo
    2399              : {
    2400              : public:
    2401              : 
    2402              :         // TODO FIXME
    2403              :         // wenn zwei an Kreuzungen endende Klüfte nur eine edge voneinander entfernt sind
    2404              :         // dann ist ein edge split an allen Ecken notwendig, die die beiden Problemzonen
    2405              :         // miteinander verbinden
    2406              :         // eventuell muss man danach die ganze Prozedur nochmal von vorne anfangen
    2407              :         // alternativ überlegen, ob man solche Punkte schon vor allen Segmentbildungen
    2408              :         // heraus filtern kann, etwa mit der altmodischen Art und Weise, wie anfangs,
    2409              :         // mit Loops über die Fracture faces...... um mindestens diese Stellen zu finden.....
    2410              :         // und gleich ein split edge an allen notwendigen Verbindungen durch zu führen.....
    2411              :         // hätte man die alte Methode vielleicht behalten sollen.......
    2412              : 
    2413              :         using ManifelPair = std::pair<MANIFEL,MANIFEL>;
    2414              : 
    2415              :         template<   typename = std::enable_if< std::is_pointer<MANIFEL>::value>,
    2416              :                                 typename = std::enable_if< std::is_pointer<VRTXTYP>::value>
    2417              :                         >
    2418            0 :         EndingCrossingFractSegmentInfo( VRTXTYP const & vrt,
    2419              :                                                                         MANIFEL const & endingFractManifCutting,
    2420              :                                                                         std::vector<MANIFEL> const & vecEndingFractManifNotCutting,
    2421              :                                                                         LOWDIMEL const & oldLowDimElCut,
    2422              :                                                                         ManifelPair const & pairNeighbouredFractClosedManifEl,
    2423              :                                                                         LOWDIMEL const & shiftDirectionElm,
    2424              :                                                                         std::vector<LOWDIMEL> const & vecLowDimElmsOfNotCuttingManifs,
    2425              :                                                                         INDEXTYP sudoFractEnding,
    2426              :                                                                         INDEXTYP sudoFractNotEnding
    2427              :                                                                   )
    2428              :         :
    2429            0 :                 m_isEndingCleft(true),
    2430            0 :                 m_unclosedVrtx(vrt),
    2431            0 :                 m_endingFractManifCutting(endingFractManifCutting),
    2432            0 :                 m_vecEndingFractManifNotCutting(vecEndingFractManifNotCutting),
    2433            0 :                 m_pairNeighbouredFractClosedManifEl(pairNeighbouredFractClosedManifEl),
    2434              :                 m_vecClosedFracManifElNoNeighbr(std::vector<MANIFEL>()),
    2435            0 :                 m_oldLowDimElCut( oldLowDimElCut ),
    2436            0 :                 m_vecLowDimElmsOfNotCuttingManifs(vecLowDimElmsOfNotCuttingManifs),
    2437            0 :                 m_shiftDirectionElm(shiftDirectionElm),
    2438            0 :                 m_sudoFractEnding(sudoFractEnding),
    2439            0 :                 m_sudoFractNotEnding(sudoFractNotEnding),
    2440              :                 m_vecFulldimEl(std::vector<FULLDIMEL>()),
    2441            0 :                 m_shiftVrtx(nullptr),
    2442            0 :                 m_hiddenCutManifEl(nullptr)
    2443              :         {
    2444            0 :         };
    2445              : 
    2446              :         template<   typename = std::enable_if< std::is_pointer<MANIFEL>::value>,
    2447              :                                 typename = std::enable_if< std::is_pointer<VRTXTYP>::value>
    2448              :                         >
    2449              :         // if there is no ending fract manif no cutting available
    2450              :         EndingCrossingFractSegmentInfo( VRTXTYP const & vrt,
    2451              :                                                                         MANIFEL const & endingFractManifCutting,
    2452              :                                                                         LOWDIMEL const & oldLowDimElCut,
    2453              :                                                                         ManifelPair const & pairNeighbouredFractClosedManifEl,
    2454              :                                                                         LOWDIMEL const & shiftDirectionElm,
    2455              :                                                                         int sudoFractEnding,
    2456              :                                                                         int sudoFractNotEnding
    2457              :                                                                   )
    2458              :         :
    2459              :                 m_isEndingCleft(true),
    2460              :                 m_unclosedVrtx(vrt),
    2461              :                 m_endingFractManifCutting(endingFractManifCutting),
    2462              :                 m_vecEndingFractManifNotCutting(std::vector<MANIFEL>()),
    2463              :                 m_pairNeighbouredFractClosedManifEl(pairNeighbouredFractClosedManifEl),
    2464              :                 m_vecClosedFracManifElNoNeighbr(std::vector<MANIFEL>()),
    2465              :                 m_oldLowDimElCut( oldLowDimElCut ),
    2466              :                 m_vecLowDimElmsOfNotCuttingManifs(std::vector<LOWDIMEL>()),
    2467              :                 m_shiftDirectionElm(shiftDirectionElm),
    2468              :                 m_sudoFractEnding(sudoFractEnding),
    2469              :                 m_sudoFractNotEnding(sudoFractNotEnding),
    2470              :                 m_vecFulldimEl(std::vector<FULLDIMEL>()),
    2471              :                 m_shiftVrtx(nullptr),
    2472              :                 m_hiddenCutManifEl(nullptr)
    2473              :         {
    2474              :         };
    2475              : 
    2476              :         template<   typename = std::enable_if< std::is_pointer<MANIFEL>::value>,
    2477              :                                 typename = std::enable_if< std::is_pointer<LOWDIMEL>::value>,
    2478              :                                 typename = std::enable_if< std::is_pointer<VRTXTYP>::value>,
    2479              :                                 typename = std::enable_if< std::is_integral<INDEXTYP>::value>
    2480              :                         >
    2481              :         // if there is no ending fract manif no cutting available
    2482              :         EndingCrossingFractSegmentInfo()
    2483              :         :
    2484              :                 m_isEndingCleft(false),
    2485              :                 m_unclosedVrtx(nullptr),
    2486              :                 m_endingFractManifCutting(nullptr),
    2487              :                 m_vecEndingFractManifNotCutting(std::vector<MANIFEL>()),
    2488              :                 m_pairNeighbouredFractClosedManifEl(ManifelPair(nullptr,nullptr)),
    2489              :                 m_vecClosedFracManifElNoNeighbr(std::vector<MANIFEL>()),
    2490              :                 m_oldLowDimElCut( nullptr ),
    2491              :                 m_vecLowDimElmsOfNotCuttingManifs(std::vector<LOWDIMEL>()),
    2492              :                 m_shiftDirectionElm(nullptr),
    2493              :                 m_sudoFractEnding(std::numeric_limits<INDEXTYP>::max()),
    2494              :                 m_sudoFractNotEnding(std::numeric_limits<INDEXTYP>::max()),
    2495              :                 m_vecFulldimEl(std::vector<FULLDIMEL>()),
    2496              :                 m_shiftVrtx(nullptr),
    2497              :                 m_hiddenCutManifEl(nullptr)
    2498              :         {
    2499              :         };
    2500              : 
    2501            0 :         bool schluckShiftVrtx( VRTXTYP const & shiftVrtx )
    2502              :         {
    2503              : 
    2504            0 :                 if(    m_shiftVrtx != nullptr
    2505            0 :                         && shiftVrtx != m_shiftVrtx
    2506              :                   )
    2507              :                 {
    2508              :                         UG_LOG("Shift Vertex already set different " << std::endl);
    2509            0 :                         UG_THROW("Shift Vertex already set different " << std::endl);
    2510              :                         return false;
    2511              :                 }
    2512              : 
    2513            0 :                 if( shiftVrtx != nullptr )
    2514              :                 {
    2515            0 :                         m_shiftVrtx = shiftVrtx;
    2516            0 :                         return true;
    2517              :                 }
    2518              : 
    2519              :                 // else
    2520              : 
    2521              : //              UG_LOG("SHift vertex already set " << std::endl);
    2522              : //              UG_THROW("SHift vertex already set " << std::endl);
    2523              : 
    2524              :                 return false;
    2525              :         }
    2526              : 
    2527              :         VRTXTYP const spuckShiftVrtx() const
    2528              :         {
    2529            0 :                 return m_shiftVrtx;
    2530              : //              if( m_shiftVrtx != nullptr )
    2531              : //              {
    2532              : //                      shiftVrtx = m_shiftVrtx;
    2533              : //                      return true;
    2534              : //              }
    2535              : //
    2536              : //              return false;
    2537              :         }
    2538              : 
    2539              :         bool isEndingCleft() { return m_isEndingCleft; }
    2540              : 
    2541              :         // schluck
    2542              : 
    2543              :         bool schluckClosedFracManifElNoNeighbr( MANIFEL const & closFracME )
    2544              :         {
    2545              :                 return schluckElem( closFracME, m_vecClosedFracManifElNoNeighbr );
    2546              : 
    2547              :         }
    2548              : 
    2549              :         bool schluckVecClosedFracManifElNoNeighbr( std::vector<MANIFEL> const & vecClosFracME )
    2550              :         {
    2551            0 :                 return schluckVecElem( vecClosFracME, m_vecClosedFracManifElNoNeighbr );
    2552              :         }
    2553              : 
    2554              :         bool schluckFulldimElm( FULLDIMEL const & fuDiEl )
    2555              :         {
    2556              :                 return schluckElem( fuDiEl, m_vecFulldimEl );
    2557              :         }
    2558              : 
    2559              :         bool schluckVecFulldimElm( std::vector<FULLDIMEL> const & vecFuDiEl )
    2560              :         {
    2561            0 :                 return schluckVecElem( vecFuDiEl, m_vecFulldimEl );
    2562              :         }
    2563              : 
    2564              :         // spuck
    2565              : 
    2566              : //      bool spuckUnclosedVrtx( VRTXTYP & vrt )
    2567              : //      {
    2568              : //              vrt = m_unclosedVrtx;
    2569              : //              return true;
    2570              : //      }
    2571              : //
    2572              : //      bool spuckVecClosedFracManifElNoNeighbr( std::vector<MANIFEL> & vecClosFracManifEl )
    2573              : //      {
    2574              : //              vecClosFracManifEl = m_vecClosedFracManifElNoNeighbr;
    2575              : //
    2576              : //              return (m_vecClosedFracManifElNoNeighbr.size() != 0 );
    2577              : //      }
    2578              : //
    2579              : //      bool spuckEndingFractManifCutting( MANIFEL & endingFractManifCutting )
    2580              : //      {
    2581              : //              endingFractManifCutting = m_endingFractManifCutting;
    2582              : //              return true;
    2583              : //      }
    2584              : //
    2585              : //      bool spuckEndingFractManifNotCutting( MANIFEL & efmnc )
    2586              : //      {
    2587              : //              efmnc = m_endingFractManifNotCutting;
    2588              : //              return true;
    2589              : //      }
    2590              : //
    2591              : //      bool spuckOldLowDimElCut( LOWDIMEL & ldec )
    2592              : //      {
    2593              : //              ldec = m_oldLowDimElCut;
    2594              : //              return true;
    2595              : //      }
    2596              : //
    2597              : //      bool spuckPairNeighbouredFractClosedManifEl( ManifelPair & neighFracClosME )
    2598              : //      {
    2599              : //              neighFracClosME = m_pairNeighbouredFractClosedManifEl;
    2600              : //              return true;
    2601              : //      }
    2602              : 
    2603              :         VRTXTYP const spuckUnclosedVrtx() const
    2604              :         {
    2605            0 :                 return m_unclosedVrtx;
    2606              :         }
    2607              : 
    2608              :         std::vector<MANIFEL> const spuckVecClosedFracManifElNoNeighbr() const
    2609              :         {
    2610            0 :                 return m_vecClosedFracManifElNoNeighbr;
    2611              :         }
    2612              : 
    2613              :         MANIFEL const spuckEndingFractManifCutting() const
    2614              :         {
    2615            0 :                 return m_endingFractManifCutting;
    2616              :         }
    2617              : 
    2618              :         std::vector<MANIFEL> const spuckVecEndingFractManifNotCutting() const
    2619              :         {
    2620            0 :                 return m_vecEndingFractManifNotCutting;
    2621              :         }
    2622              : 
    2623              :         LOWDIMEL const spuckOldLowDimElCut() const
    2624              :         {
    2625            0 :                 return m_oldLowDimElCut;
    2626              :         }
    2627              : 
    2628              :         std::vector<LOWDIMEL> const spuckVecLowDimElmsOfNotCuttingManifs()
    2629              :         {
    2630              :                 return m_vecLowDimElmsOfNotCuttingManifs;
    2631              :         }
    2632              : 
    2633              :         ManifelPair const spuckPairNeighbouredFractClosedManifEl() const
    2634              :         {
    2635            0 :                 return m_pairNeighbouredFractClosedManifEl;
    2636              :         }
    2637              : 
    2638            0 :         INDEXTYP const spuckSudoFractEnding() const { return m_sudoFractEnding; }
    2639              :         INDEXTYP const spuckSudoFractNotEnding() const { return m_sudoFractNotEnding; }
    2640              : 
    2641              :         std::vector<FULLDIMEL> const spuckVecFulldimEl() const
    2642              :         {
    2643            0 :                 return m_vecFulldimEl;
    2644              :         }
    2645              : 
    2646              :         // shift element edge
    2647              : 
    2648              : 
    2649              :         template<   typename = std::enable_if< std::is_pointer<LOWDIMEL>::value>
    2650              :                         >
    2651              :         LOWDIMEL const spuckLowdimElmShiftDirection() const
    2652              :         {
    2653            0 :                 return m_shiftDirectionElm;
    2654              :         }
    2655              : 
    2656              :         bool schluckHiddenCutFractManifEl( MANIFEL const & manifel )
    2657              :         {
    2658            0 :                 if( m_hiddenCutManifEl == nullptr && manifel != m_hiddenCutManifEl )
    2659              :                 {
    2660            0 :                         m_hiddenCutManifEl = manifel;
    2661              :                         return true;
    2662              :                 }
    2663              : 
    2664              :                 return false;
    2665              :         }
    2666              : 
    2667              :         MANIFEL const spuckHiddenCutFractManifEl() const
    2668              :         {
    2669            0 :                 return m_hiddenCutManifEl;
    2670              :         }
    2671              : 
    2672              : private:
    2673              : 
    2674              :         bool m_isEndingCleft;
    2675              : 
    2676              :         // TODO FIXME vielleicht statt Manifel die Klasse,  Attached Fracture Objekte? mit richtig geordneten Edges?
    2677              : 
    2678              :         VRTXTYP m_unclosedVrtx;
    2679              :         MANIFEL m_endingFractManifCutting;
    2680              : //      MANIFEL m_endingFractManifNotCutting;
    2681              :         std::vector<MANIFEL> m_vecEndingFractManifNotCutting;
    2682              : 
    2683              :         ManifelPair m_pairNeighbouredFractClosedManifEl;
    2684              : 
    2685              :         // NOTE here only those which do not have a common edge with the ending cleft!
    2686              :         std::vector<MANIFEL> m_vecClosedFracManifElNoNeighbr;
    2687              : 
    2688              :         LOWDIMEL m_oldLowDimElCut; // common edge between ending frac face with one sudo and durchgehende frac faces with another sudo
    2689              : //      LOWDIMEL m_newLowDimElCut;
    2690              : 
    2691              :         std::vector<LOWDIMEL> m_vecLowDimElmsOfNotCuttingManifs;
    2692              : 
    2693              :         LOWDIMEL m_shiftDirectionElm;
    2694              : 
    2695              :         INDEXTYP m_sudoFractEnding;
    2696              :         INDEXTYP m_sudoFractNotEnding;
    2697              : 
    2698              :         std::vector<FULLDIMEL> m_vecFulldimEl;
    2699              : 
    2700              :         VRTXTYP m_shiftVrtx;
    2701              : 
    2702              :         MANIFEL m_hiddenCutManifEl;
    2703              : 
    2704              :         template <typename ELEMTYP>
    2705            0 :         bool schluckElem( ELEMTYP const & anotherEl, std::vector<ELEMTYP> & vecElmKnown )
    2706              :         {
    2707              :                 bool elemNotKnown = true;
    2708              : 
    2709            0 :                 for( ELEMTYP me : vecElmKnown )
    2710              :                 {
    2711            0 :                         if( me == anotherEl )
    2712              :                         {
    2713              :                                 elemNotKnown = false;
    2714              :                                 break;
    2715              :                         }
    2716              :                 }
    2717              : 
    2718            0 :                 if( elemNotKnown )
    2719            0 :                         vecElmKnown.push_back(anotherEl);
    2720              : 
    2721            0 :                 return elemNotKnown;
    2722              :         }
    2723              : 
    2724              :         template <typename ELEMTYP>
    2725            0 :         bool schluckVecElem( std::vector<ELEMTYP> const & anotherVecEl, std::vector<ELEMTYP> & vecElmKnown )
    2726              :         {
    2727              :                 bool someElemsUnknown = false;
    2728              : 
    2729            0 :                 for( ELEMTYP me : anotherVecEl )
    2730              :                 {
    2731            0 :                         if( schluckElem( me, vecElmKnown ) )
    2732              :                         {
    2733              :                                 someElemsUnknown = true;
    2734              :                         }
    2735              :                 }
    2736              : 
    2737            0 :                 return someElemsUnknown;
    2738              :         }
    2739              : };
    2740              : 
    2741              : //////////////////////////////////////////////////////////////////////////
    2742              : 
    2743              : }
    2744              : 
    2745              : }
    2746              : 
    2747              : }
    2748              : 
    2749              : #endif /* UGCORE_UGBASE_LIB_GRID_ALGORITHMS_EXTRUSION_SUPPORT3D_H_ */
        

Generated by: LCOV version 2.0-1