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

Generated by: LCOV version 2.0-1