LCOV - code coverage report
Current view: top level - ugbase/lib_grid/algorithms/extrusion - ArteExpandFracs3D.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 1356 0
Test Date: 2026-06-01 23:54:59 Functions: 0.0 % 43 0

            Line data    Source code
       1              : /*
       2              :  * ArteExpandFracs3D.cpp
       3              :  *
       4              :  *  Created on: 06.10.2024
       5              :  *      Author: Markus M. Knodel
       6              :  *
       7              :  *  * expand fractures using the Arte algorithm, 3D case
       8              :  *
       9              :  * Author: Markus Knodel, inspired by Arte from Fuchs and Sebastian Reiters code for fracture expansion without Arte
      10              :  *
      11              :  * implementing a class that gives the basic tools for Arte in 3D
      12              :  * might be templated at a later stage to fulfill 2D and 3D purposes, if suitable
      13              :  * ( so far 2D case one entire function, not so perfect, but running....)
      14              :  *
      15              :  *
      16              :  * This file is part of UG4.
      17              :  *
      18              :  * UG4 is free software: you can redistribute it and/or modify it under the
      19              :  * terms of the GNU Lesser General Public License version 3 (as published by the
      20              :  * Free Software Foundation) with the following additional attribution
      21              :  * requirements (according to LGPL/GPL v3 §7):
      22              :  *
      23              :  * (1) The following notice must be displayed in the Appropriate Legal Notices
      24              :  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
      25              :  *
      26              :  * (2) The following notice must be displayed at a prominent place in the
      27              :  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
      28              :  *
      29              :  * (3) The following bibliography is recommended for citation and must be
      30              :  * preserved in all covered files:
      31              :  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
      32              :  *   parallel geometric multigrid solver on hierarchically distributed grids.
      33              :  *   Computing and visualization in science 16, 4 (2013), 151-164"
      34              :  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
      35              :  *   flexible software system for simulating pde based models on high performance
      36              :  *   computers. Computing and visualization in science 16, 4 (2013), 165-179"
      37              :  *
      38              :  * This program is distributed in the hope that it will be useful,
      39              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      40              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      41              :  * GNU Lesser General Public License for more details.
      42              :  */
      43              : 
      44              : 
      45              : #include "lib_grid/algorithms/geom_obj_util/geom_obj_util.h"
      46              : #include "lib_grid/callbacks/callbacks.h"
      47              : #include "lib_grid/grid/grid_util.h"
      48              : 
      49              : #include <stack>
      50              : #include <utility>
      51              : #include <vector>
      52              : #include <type_traits>
      53              : #include <limits>
      54              : #include <atomic>
      55              : #include <cstddef>
      56              : #include <bitset>
      57              : #include <string>
      58              : #include <cmath>
      59              : 
      60              : #include "support.h"
      61              : #include "support3D.h"
      62              : 
      63              : 
      64              : #include <lib_grid/algorithms/extrusion/ArteExpandFracs3D.h>
      65              : 
      66              : #include "simpleMatrixOps.h"
      67              : 
      68              : #include "DiamondInfo.h"
      69              : 
      70              : namespace ug
      71              : {
      72              : 
      73              : namespace arte
      74              : {
      75              : 
      76            0 : ArteExpandFracs3D::ArteExpandFracs3D(
      77              :                 Grid & grid, SubsetHandler & sh,
      78              :             std::vector<FractureInfo> const & fracInfos,
      79            0 :                 bool diamondsOnlyPreform, bool establishDiamonds )
      80            0 :         : m_grid(grid),
      81            0 :           m_sh(sh),
      82            0 :           m_fracInfos(fracInfos),
      83            0 :           m_diamondsOnlyPreform(diamondsOnlyPreform),
      84            0 :           m_establishDiamonds(establishDiamonds),
      85              :           m_aaPos(Grid::VertexAttachmentAccessor<APosition>()),
      86              : //        m_facDescr(FaceDescriptor()),
      87              : //        m_volDescr(VolumeDescriptor()),
      88              :           m_fracInfosBySubset(std::vector<FractureInfo>()),
      89              :           //m_sel(Selector()),
      90              :           m_aAdjMarkerVFP(AttVertFracProp()),
      91              :           m_aaMarkVrtVFP( Grid::VertexAttachmentAccessor<AttVertFracProp>()),
      92              : //        m_aAdjMarkerVFP(AttVertFracProp()),
      93              :           m_aaMarkEdgeVFP(Grid::EdgeAttachmentAccessor<AttVertFracProp>()),
      94              :           m_aAdjMarkerFaceIsFracB(ABool()),
      95              :           m_aaMarkFaceIsFracB(Grid::FaceAttachmentAccessor<ABool>()),
      96              : //        m_aaMarkFaceHasUnclosedFracSideB(Grid::FaceAttachmentAccessor<ABool>()),
      97              : //        m_aAdjMarkerVrtxHasUnclosedFracB(ABool()),
      98              : //        m_aaMarkVrtxHasUnclosedFracB(Grid::VertexAttachmentAccessor<ABool>()),
      99              :           m_aAdjMarkerFaceWithEndingCrossingCleft(ABool()),
     100              :           m_aaMarkFaceWithEndingCrossingCleft(Grid::FaceAttachmentAccessor<ABool>()),
     101              :           m_aAdjMarkerVrtxAtEndingCrossingCleft(ABool()),
     102              :           m_aaMarkVrtxAtEndingCrossingCleft(Grid::VertexAttachmentAccessor<ABool>()),
     103              : //        m_aAdjMarkerVrtx2AtInnerEndOfEndingCrossingFract(ABool()),
     104              : //        m_aaMarkVrtx2AtInnerEndOfEndingCrossingFract(Grid::VertexAttachmentAccessor<ABool>()),
     105            0 :           m_needToSplitEdgesConnectingNeighbrdEndingCrossCleftVrtx(false),
     106              :           m_originalFractureFaces(std::vector<Face*>()),
     107              : //        m_attVrtVec(AttVrtVec()),
     108              : //        m_aaVrtVecVol( Grid::VolumeAttachmentAccessor<AttVrtVec>() ),
     109              :           m_aAdjInfoEdges(AttVecEdge()),
     110              :           m_aAdjInfoFaces(AttVecFace()),
     111              : //        m_aAdjInfoVols(AttVecVol()),
     112              :           m_aaVrtInfoAssoEdges( Grid::VertexAttachmentAccessor<AttVecEdge>()),
     113              :           m_aaVrtInfoAssoFaces( Grid::VertexAttachmentAccessor<AttVecFace>()),
     114              : //        m_aaVrtInfoAssoVols( Grid::VertexAttachmentAccessor<AttVecVol>()),
     115              : //        m_aAdjInfoAVVFT( AttVecVertFracTrip() ),
     116              : //        m_aaVrtInfoFraTri(Grid::VertexAttachmentAccessor<AttVecVertFracTrip>()),
     117              : //        m_vrtxFractrQuadrplVec(VrtxFractrQuadrplArte3DVec())
     118              :           m_attVrtVec(AttVrtVec()),
     119              :           m_aaVrtVecVol( Grid::VolumeAttachmentAccessor<AttVrtVec>() ),
     120              :           m_vecCrossVrtInf(std::vector<CrossVertInf>()),
     121              : //        m_aAdjVolElmInfo(AttVecAttachedVolumeElemInfo()),
     122              : //        m_aaVolElmInfo(Grid::VertexAttachmentAccessor<AttVecAttachedVolumeElemInfo>()),
     123              :           m_attAdjVecSegVolElmInfo( AttVecSegmentVolElmInfo() ),
     124              :           m_accsAttVecSegVolElmInfo( Grid::VertexAttachmentAccessor<AttVecSegmentVolElmInfo>() ),
     125              :           m_attVecSegmLimSid(AttVecSegmLimSid()),
     126              :           m_vrtxAttAccsVecSegmLimSid(Grid::VertexAttachmentAccessor<AttVecSegmLimSid>()),
     127              :           m_vecEdgeDirectConnectingEndingCrossCleftVrtcs( std::vector<Edge* >() ),
     128              :           m_vecEndCrossFractSegmInfo( VecEndingCrossingFractureSegmentInfo() ),
     129              : //        m_vecEndCrossFractSegmInfo(VecEndingCrossingFractureSegmentInfo()),
     130              :           m_attAtVrtxVecEndingCrossFractSegmInfo(AttVecEndingCrossingFractureSegmentInfo()),
     131              :           m_vrtxAttAccsVecEndingCrossFractSegmInfo(Grid::VertexAttachmentAccessor<AttVecEndingCrossingFractureSegmentInfo>()),
     132              : //        m_attAtVrtxIfVrtxIsEndingCrossingCleftVrtx(ABool()),
     133              : //        m_vrtxAttAccsVrtxIsEndingCrossingCleftVrtx(Grid::VertexAttachmentAccessor<ABool>()),
     134              :           m_attAtFaceIfFaceIsSegmLimFaceEndingCrossingCleft(ABool()),
     135              :           m_facAttAccsIfFaceIsSegmLimFaceEndingCrossingCleft(Grid::FaceAttachmentAccessor<ABool>()),
     136              :           m_attAtVolIfVolTouchesEndingCrossingCleft(ABool()),
     137              :           m_volAttAccsVolTouchesEndingCrossingCleft(Grid::VolumeAttachmentAccessor<ABool>()),
     138              :           m_attAtVrtxIfVrtxArisesFromExpandedEndingCrossingCleft(ABool()),
     139              :           m_vrtxAttAccsVrtxArisesFromExpandedEndingCrossingCleft(Grid::VertexAttachmentAccessor<ABool>()),
     140              :           m_vrtxArisesFromExpandedEndingCrossingCleft(std::vector<Vertex*>()),
     141            0 :           m_allowedSqueeze(0.9),
     142              :           m_vrtcsViolatingExpansion(std::vector<Vertex*>()),
     143              :           m_volsViolatingExpansion(std::vector<Volume*>()),
     144            0 :           m_vecVolManifVrtxCombiToShrink4Diams(VecVolManifVrtxCombi())
     145              : //        m_diamInfos3D(std::vector<DiamantInfo3D>()),
     146              : //        m_oldNewVrtcs4Diams(std::vector<VrtxPair>())
     147              : {
     148              : //      // Notloesung, nicht in die erste Initialisierung vor geschweifter Klammer, da copy constructor privat
     149            0 :         m_sel = Selector();
     150              : 
     151              :         UG_LOG("----------------------------" << std::endl);
     152              :         UG_LOG("----------------------------" << std::endl);
     153              : 
     154              :         UG_LOG("EXPANDING PROCEDURE ARTE 3D " << std::endl);
     155              : 
     156            0 :         for( FractureInfo const & fi : m_fracInfos )
     157              :         {
     158            0 :                 UG_LOG("Fracture old " << fi.subsetIndex << " new " << fi.newSubsetIndex << " width " << fi.width << std::endl);
     159              :         }
     160              : 
     161              :         UG_LOG("----------------------------" << std::endl);
     162              : 
     163            0 :         UG_LOG("DIAMONDS pre " << m_diamondsOnlyPreform << " and establish " << m_establishDiamonds << std::endl);
     164              : 
     165              :         UG_LOG("----------------------------" << std::endl);
     166              :         UG_LOG("----------------------------" << std::endl);
     167            0 : }
     168              : 
     169              : 
     170            0 : ArteExpandFracs3D::~ArteExpandFracs3D()
     171              : {
     172              :         //  Auto-generated destructor stub
     173            0 : }
     174              : 
     175            0 : bool ArteExpandFracs3D::run( bool & needToRestart )
     176              : {
     177            0 :         needToRestart = false;
     178              : 
     179              : //      if( ! m_establishDiamonds )
     180              : //      {
     181              : //              UG_LOG("NO DIAMS " << std::endl);
     182              : //      }
     183              : 
     184            0 :         if( ! initialize() )
     185              :                 return false;
     186              : 
     187              :         UG_LOG("initialisiert" << std::endl);
     188              : 
     189            0 :         if( ! setSelector() )
     190              :                 return false;
     191              : 
     192              :         UG_LOG("selektiert" << std::endl);
     193              : 
     194            0 :         if( ! attachMarkers() )
     195              :                 return false;
     196              : 
     197              :         UG_LOG("attached" << std::endl);
     198              : 
     199            0 :         int splittedEdges = splitInnerFreeFracEdgs();
     200              : 
     201            0 :         UG_LOG("splitted edges " << splittedEdges << std::endl);
     202              : //
     203              : //      return false;
     204              : //
     205              : //      UG_LOG("Splitted inner free frac edges" << splittedEdges << std::endl);
     206              : 
     207            0 :         if( ! countAndSelectFracBaseNums() )
     208              :                 return false;
     209              : 
     210              :         UG_LOG("gezaehlt" << std::endl);
     211              : 
     212              : //      constexpr bool assignFracInfosFirst = true;
     213              : //
     214              : //      if( assignFracInfosFirst )
     215              : //      {
     216            0 :         if( ! assignOrigFracInfos() )
     217              :                 return false;
     218              : 
     219              :         UG_LOG("assigniert zuerst " << std::endl);
     220              : 
     221            0 :         if( ! enableVolOptAutoGenFac() )
     222              :         {
     223              :                 UG_LOG("autogen war schon eingestellt" << std::endl);
     224              :         }
     225              :         else
     226              :         {
     227              :                 UG_LOG("Autogen einstellen" << std::endl);
     228              :         }
     229              :         // TODO FIXME für was gebraucht????
     230              : 
     231              : //      }
     232              : 
     233              : //      constexpr bool generVrtInfoFirst = true;
     234              : //
     235              : //      if( generVrtInfoFirst )
     236              : //      {
     237              : //      if( ! generateVertexInfos() )
     238              : //              return false;
     239              : //
     240              : //      UG_LOG("generiert zuerst " << std::endl);
     241              : 
     242              : //      }
     243              : 
     244              : //      if( ! prepareStasi() )
     245              : //              return false;
     246              : //
     247              : //      UG_LOG("Stasi vorbereitet " << std::endl);
     248              : 
     249            0 :         if( ! distinguishSegments() )
     250              :                 return false;
     251              : 
     252              :         UG_LOG("Segmente erzeugt " << std::endl);
     253              : 
     254              : 
     255              :         UG_LOG("check unclosed frac faces" << std::endl);
     256              : 
     257            0 :         if( ! establishSegmentLimitingSidesInfo() )
     258              :                 return false;
     259              : 
     260              :         UG_LOG("established Segment limiting sides info" << std::endl);
     261              : 
     262            0 :         if( ! detectEndingCrossingCleftsSegmBased() )
     263              :         {
     264            0 :                 if( m_needToSplitEdgesConnectingNeighbrdEndingCrossCleftVrtx )
     265              :                 {
     266            0 :                         needToRestart = true;
     267              :                         UG_LOG("Restart due to splitted edges" << std::endl);
     268              :                 }
     269              :                 else
     270              :                 {
     271            0 :                         needToRestart = false;
     272              :                         UG_LOG("No need to restart due to splitted edges" << std::endl);
     273              :                 }
     274              : 
     275            0 :                 return false;
     276              :         }
     277              : 
     278              :         UG_LOG("Ending crossing clefts detected" << std::endl);
     279              : 
     280            0 :         if( ! seletForSegmented() )
     281              :                 return false;
     282              : 
     283              :         UG_LOG("Closed Open Vertex Fract untersucht " << std::endl);
     284              : 
     285              : //      if( ! assignFracInfosFirst )
     286              : //      {
     287              : //              if( ! assignOrigFracInfos() )
     288              : //                      return false;
     289              : //
     290              : //              UG_LOG("assigniert danach " << std::endl);
     291              : //
     292              : //      }
     293              : 
     294              : 
     295            0 :         if( ! establishNewVrtBase() )
     296              :                 return false;
     297              : 
     298              :         UG_LOG("etabliert" << std::endl);
     299              : 
     300              : //      if( ! generVrtInfoFirst )
     301              : //      {
     302              : //
     303              : //              if( ! generateVertexInfos() )
     304              : //                      return false;
     305              : //
     306              : //              UG_LOG("generiert danach " << std::endl);
     307              : //      }
     308              : 
     309            0 :         if( ! createConditionForNewVrtcs() )
     310              :                 return false;
     311              : 
     312              :         UG_LOG("kreiert" << std::endl);
     313              : 
     314            0 :         if( ! loop2EstablishNewVertices() )
     315              :                 return false;
     316              : 
     317              :         UG_LOG("loopiert" << std::endl);
     318              : 
     319              :         UG_LOG("under construction " << std::endl);
     320              : 
     321            0 :         if( ! createNewElements() )
     322              :                 return false;
     323              : 
     324              :         UG_LOG("new elements created " << std::endl);
     325              : 
     326            0 :         if( ! detachMarkers() )
     327              :                 return false;
     328              : 
     329              :         UG_LOG("detachiert" << std::endl);
     330              : 
     331              : //      assignDebugSubsets( false );
     332              : 
     333              :         UG_LOG("Debug subsets assigned" << std::endl );
     334              : 
     335            0 :         IndexType numDelEndCrossCleftFacs = deleteEndingCrossingCleftOrigFacs();
     336              : 
     337              :         UG_LOG("deleted ending crossing cleft changed faces and direction edges " << numDelEndCrossCleftFacs << std::endl);
     338              : 
     339            0 :         if( m_establishDiamonds )
     340              :         {
     341            0 :                 if( ! createTheDiamonds() )
     342              :                 {
     343              :                         UG_LOG("Diamond creation failed " << std::endl);
     344            0 :                         return false;
     345              : //                      UG_THROW("Diamonds not creatable" << std::endl);
     346              :                 }
     347              :         }
     348              : 
     349              :         UG_LOG("diamonds created if desired" << std::endl);
     350              : 
     351            0 :         return true;
     352              : }
     353              : 
     354              : ////////////////////////////////////////////////
     355              : 
     356            0 : bool ArteExpandFracs3D::splitEdgesOfNeighboredEndingCrossingFracVrtcs()
     357              : {
     358              : //      IndexType numberSplittedEdges = 0;
     359              : 
     360              :         // TODO FIXME vergleichen, was bei den debug Ecken alles an Randvertizes ist, und was bei
     361              :         // den hochstehenden Edges für Randvertizes sind, ob da was verloren gegangen ist
     362              :         // oder ob bei den modernen SegmentEnding Infos was fehlt an Vertizes.....
     363              :         // angefangen mit dem simplen Beispiel!
     364              :         // wenn das klappt, können die debug m_d_ Variablen entfernt werden.....
     365              : 
     366              :         UG_LOG("NUMBER EDGES DIRECT " << m_vecEdgeDirectConnectingEndingCrossCleftVrtcs.size() << std::endl );
     367              : 
     368              :         UG_LOG("NUMBER VERTICES FRAC SEGMENTS " << m_vecEndCrossFractSegmInfo.size() << std::endl );
     369              : 
     370            0 :         for( Edge * edg : m_vecEdgeDirectConnectingEndingCrossCleftVrtcs )
     371              :         {
     372              : 
     373            0 :                 UG_LOG("trying to split edge " << CalculateCenter( edg, m_aaPos ) << std::endl);
     374              : 
     375            0 :                 UG_LOG("E VERTEX ONE " << m_aaPos[ edg->vertex(0) ] << std::endl);
     376            0 :                 UG_LOG("E VERTEX TWO " << m_aaPos[ edg->vertex(1) ] << std::endl);
     377              : 
     378            0 :                 for( EndingCrossingFractureSegmentInfo const & ecfsiOne : m_vecEndCrossFractSegmInfo )
     379              :                 {
     380              :                         Vertex * vrtOne = ecfsiOne.spuckUnclosedVrtx();
     381              : 
     382            0 :                         UG_LOG("V ONE " << m_aaPos[vrtOne] << std::endl);
     383              : 
     384            0 :                         for( EndingCrossingFractureSegmentInfo const & ecfsiTwo : m_vecEndCrossFractSegmInfo )
     385              :                         {
     386              :                                 Vertex * vrtTwo = ecfsiTwo.spuckUnclosedVrtx();
     387              : 
     388            0 :                                 UG_LOG("V TWO " << m_aaPos[vrtTwo] << std::endl);
     389              : 
     390            0 :                                 if( vrtOne != vrtTwo )
     391              :                                 {
     392            0 :                                         if( EdgeContains(edg, vrtOne) && EdgeContains( edg, vrtTwo) )
     393              :                                         {
     394              :                                                 UG_LOG("Edge needs to be splitted" << std::endl);
     395              : 
     396            0 :                                                 int suse = m_sh.num_subsets();
     397              : 
     398            0 :                                                 m_sh.assign_subset( edg, suse );
     399              : 
     400              :                                                 UG_LOG("need to detach markers" << std::endl);
     401            0 :                                                 detachMarkers();
     402              : 
     403            0 :                                                 vector3 center = CalculateCenter(edg, m_aaPos);
     404            0 :                                                 UG_LOG("splitting ECCV edge at " << center << std::endl);
     405            0 :                                                 RegularVertex* vrtSE = SplitEdge<RegularVertex>(m_grid, edg, false);
     406              :                                                 m_aaPos[vrtSE] = center;
     407              : 
     408              :                                                 UG_LOG("Edge splitted, please restart process with the thus changed geometry" << std::endl);
     409              : 
     410              :                                                 return true;
     411              : 
     412              :                                         }
     413              : 
     414              :                                 }
     415              : 
     416              :                         }
     417              : 
     418              : 
     419              :                 }
     420              :         }
     421              : 
     422              :         return false;
     423              : 
     424              : //      if( numberSplittedEdges > 0 )
     425              : //              UG_LOG("Edge splitted, please restart process with the thus changed geometry, new edges " << numberSplittedEdges << std::endl);
     426              : //
     427              : //      return numberSplittedEdges;
     428              : 
     429              :         // TODO FIXME das ganze nochmal mit dem Debug Zeug
     430              : 
     431              : //      UG_LOG("DEBUG" << std::endl);
     432              : //
     433              : //      int suse = m_sh.num_subsets();
     434              : //
     435              : //      for( Edge * edg : m_d_allContributingEdges )
     436              : //      {
     437              : //              UG_LOG("E VERTEX ONE " << m_aaPos[ edg->vertex(0) ] << std::endl);
     438              : //              UG_LOG("E VERTEX TWO " << m_aaPos[ edg->vertex(1) ] << std::endl);
     439              : //
     440              : //              for( Vertex * vrtOne : m_d_endingCrossingCleftVrtcs )
     441              : //              {
     442              : //                      UG_LOG("V ONE " << m_aaPos[vrtOne] << std::endl);
     443              : //
     444              : //                      for( Vertex * vrtTwo : m_d_endingCrossingCleftVrtcs )
     445              : //                      {
     446              : //
     447              : //                              UG_LOG("V Two " << m_aaPos[vrtTwo] << std::endl);
     448              : //
     449              : //                              if( vrtOne != vrtTwo )
     450              : //                              {
     451              : //                                      if( EdgeContains(edg, vrtOne) && EdgeContains( edg, vrtTwo) )
     452              : //                                      {
     453              : //                                              UG_LOG("Edge needs to be splitted" << std::endl);
     454              : //
     455              : //                                              m_sh.assign_subset( edg, suse );
     456              : //
     457              : //                                              vector3 center = CalculateCenter(edg, m_aaPos);
     458              : //                                              UG_LOG("splitting ECCV edge at " << center << std::endl);
     459              : //                                              RegularVertex* vrtSE = SplitEdge<RegularVertex>(m_grid, edg, false);
     460              : //                                              m_aaPos[vrtSE] = center;
     461              : //
     462              : //                                              UG_LOG("Edge splitted, please restart process with the thus changed geometry" << std::endl);
     463              : //
     464              : //                                              return 1;
     465              : //
     466              : //                                      }
     467              : //                              }
     468              : //                      }
     469              : //
     470              : //              }
     471              : //      }
     472              : //
     473              : //      return 0;
     474              : //
     475              : //      return false;
     476              : 
     477              : }
     478              : 
     479              : ////////////////////////////////////////////////
     480              : 
     481            0 : void ArteExpandFracs3D::assignDebugSubsets( bool intermediate )
     482              : {
     483              : //      return;
     484              : 
     485              :         std::vector<Face*> d_endingCrossingCleftFaces;
     486              :         std::vector<Face*> d_endingCrossingCleftFacesNoCut;
     487              :         std::vector<Vertex*> d_endingCrossingCleftVrtcs;
     488              :         std::vector<Edge*> d_cuttingEdges;
     489              :         std::vector<Edge*> d_shiftEdges;
     490              :         std::vector<Face*> d_crossingNeighboredNotEndingFaces;
     491              :         std::vector<Face*> d_crossingNeighboredNotEndingFacesCommEdg;
     492              :         std::vector<Face*> d_notEndingCrossingFacesNotNeighbour;
     493              :         std::vector<Volume*> d_vols;
     494              :         std::vector<Vertex*> d_shiftVrtcs;
     495              : 
     496              :         UG_LOG("Number ending crossing clefts " << m_vecEndCrossFractSegmInfo.size()  << std::endl);
     497              : 
     498            0 :         for( EndingCrossingFractureSegmentInfo const & ecfsi : m_vecEndCrossFractSegmInfo )
     499              :         {
     500            0 :                 Vertex * vrt = ecfsi.spuckUnclosedVrtx();
     501              : 
     502            0 :                 d_endingCrossingCleftVrtcs.push_back(vrt);
     503              : 
     504              :                 std::vector<Face*> vecClosFracFacNoNeig = ecfsi.spuckVecClosedFracManifElNoNeighbr();
     505              : 
     506            0 :                 for( Face * fac : vecClosFracFacNoNeig )
     507              :                 {
     508            0 :                         d_crossingNeighboredNotEndingFaces.push_back(fac);
     509              :                 }
     510              : 
     511            0 :                 Face * endingFacCut = ecfsi.spuckEndingFractManifCutting();
     512              : 
     513            0 :                 d_endingCrossingCleftFaces.push_back(endingFacCut);
     514              : 
     515            0 :                 for( Face * endingFacNoCut : ecfsi.spuckVecEndingFractManifNotCutting() )
     516              :                 {
     517            0 :                         if( endingFacNoCut != nullptr )
     518              :                         {
     519            0 :                                 d_endingCrossingCleftFacesNoCut.push_back(endingFacNoCut);
     520              :                         }
     521            0 :                 }
     522              : 
     523            0 :                 Edge * cutEdge = ecfsi.spuckOldLowDimElCut();
     524              : 
     525            0 :                 d_cuttingEdges.push_back(cutEdge);
     526              : 
     527            0 :                 std::pair<Face*,Face*> const & neighrdFacsClos = ecfsi.spuckPairNeighbouredFractClosedManifEl();
     528              : 
     529            0 :                 d_crossingNeighboredNotEndingFacesCommEdg.push_back(neighrdFacsClos.first);
     530            0 :                 d_crossingNeighboredNotEndingFacesCommEdg.push_back(neighrdFacsClos.second);
     531              : 
     532              :                 std::vector<Volume*> vols = ecfsi.spuckVecFulldimEl();
     533              : 
     534            0 :                 for( Volume * v : vols )
     535              :                 {
     536            0 :                         d_vols.push_back(v);
     537              :                 }
     538              : 
     539            0 :                 Edge * shiftEdge = ecfsi.spuckLowdimElmShiftDirection();
     540            0 :                 d_shiftEdges.push_back(shiftEdge);
     541              : 
     542              : 
     543            0 :                 if( ! intermediate )
     544              :                 {
     545            0 :                         Vertex * shiVe = ecfsi.spuckShiftVrtx();
     546              : 
     547            0 :                         if( shiVe == nullptr )
     548              :                         {
     549            0 :                                 m_sh.assign_subset(vrt, m_sh.num_subsets());
     550            0 :                                 m_sh.assign_subset(shiftEdge, m_sh.num_subsets());
     551              : 
     552              :                                 UG_LOG("no shift vertex for ending crossing cleft segment " << std::endl);
     553            0 :                                 UG_THROW("no shift vertex for ending crossing cleft segment " << std::endl);
     554              : 
     555              :                         }
     556            0 :                         d_shiftVrtcs.push_back(shiVe);
     557              :                 }
     558              : 
     559              : 
     560              : 
     561            0 :         }
     562              : 
     563            0 :         int suse = m_sh.num_subsets();
     564              : 
     565            0 :         if( ! intermediate )
     566              :         {
     567              : 
     568            0 :                 for( Face * fac : d_endingCrossingCleftFaces )
     569              :                 {
     570            0 :                         if( fac != nullptr )
     571            0 :                                 m_sh.assign_subset( fac, suse );
     572              : 
     573              :                 }
     574              : 
     575            0 :                 suse = m_sh.num_subsets();
     576              : 
     577            0 :                 for( Face * fac : d_endingCrossingCleftFacesNoCut )
     578              :                 {
     579            0 :                         if( fac != nullptr )
     580            0 :                                 m_sh.assign_subset( fac, suse );
     581              : 
     582              :                 }
     583              : 
     584            0 :                 suse = m_sh.num_subsets();
     585              : 
     586            0 :                 for( Vertex * vrt : d_endingCrossingCleftVrtcs )
     587              :                 {
     588            0 :                         if( vrt != nullptr )
     589            0 :                                 m_sh.assign_subset( vrt, suse );
     590              :                 }
     591              : 
     592            0 :                 suse = m_sh.num_subsets();
     593              : 
     594            0 :                 for( Edge * edg : d_cuttingEdges )
     595              :                 {
     596            0 :                         if( edg == nullptr )
     597              :                         {
     598              :                                 UG_LOG("NULL UNERLAUBT" << std::endl);
     599            0 :                                 UG_THROW("NULL UNERLAUBT" << std::endl);
     600              :                         }
     601              : 
     602            0 :                         m_sh.assign_subset( edg, suse );
     603              : 
     604              :                 }
     605              : 
     606            0 :                 suse = m_sh.num_subsets();
     607              : 
     608            0 :                 for( Edge * edg : d_shiftEdges )
     609              :                 {
     610            0 :                         if( edg == nullptr )
     611              :                         {
     612              :                                 UG_LOG("NULL UNERLAUBT" << std::endl);
     613            0 :                                 UG_THROW("NULL UNERLAUBT" << std::endl);
     614              :                         }
     615              : 
     616            0 :                         m_sh.assign_subset( edg, suse );
     617              : 
     618              :                 }
     619              : 
     620              : 
     621            0 :                 suse = m_sh.num_subsets();
     622              : 
     623            0 :                 for( Face * fac : d_crossingNeighboredNotEndingFaces )
     624              :                 {
     625            0 :                         if( fac != nullptr )
     626            0 :                                 m_sh.assign_subset( fac, suse );
     627              :                 }
     628              : 
     629            0 :                 suse = m_sh.num_subsets();
     630              : 
     631            0 :                 for( Face * fac : d_notEndingCrossingFacesNotNeighbour )
     632              :                 {
     633            0 :                         m_sh.assign_subset( fac, suse );
     634              :                 }
     635              : 
     636            0 :                 suse = m_sh.num_subsets();
     637              : 
     638            0 :                 for( Face * fac : d_crossingNeighboredNotEndingFacesCommEdg )
     639              :                 {
     640            0 :                         m_sh.assign_subset( fac, suse );
     641              :                 }
     642              : 
     643            0 :                 suse = m_sh.num_subsets();
     644              : 
     645            0 :                 for( Vertex * vrtx : d_shiftVrtcs )
     646              :                 {
     647            0 :                         if( vrtx != nullptr )
     648            0 :                                 m_sh.assign_subset( vrtx, suse );
     649              :                 }
     650              : 
     651              : //      suse = m_sh.num_subsets();
     652              :         }
     653              :         else
     654              :         {
     655              : 
     656            0 :                 for( Volume * v : d_vols )
     657              :                 {
     658            0 :                         if( v != nullptr )
     659            0 :                                 m_sh.assign_subset( v, suse );
     660              :                 }
     661              :         }
     662              : 
     663            0 :         return;
     664              : 
     665              : #if 0
     666              : //      if( numEndingCrossingClefts == 0 )
     667              : //              return true;
     668              : 
     669              :         // debug for ending crossing clefts
     670              : 
     671              :         suse = m_sh.num_subsets();
     672              : 
     673              :         for( Face * fac : m_d_endingCrossingCleftFaces )
     674              :         {
     675              : //              m_sh.assign_subset( fac, m_sh.num_subsets());
     676              :                 m_sh.assign_subset( fac, suse );
     677              : 
     678              :         }
     679              : 
     680              :         suse = m_sh.num_subsets();
     681              : 
     682              :         for( Vertex * vrt : m_d_endingCrossingCleftVrtcs )
     683              :         {
     684              : //              m_sh.assign_subset( vrt, m_sh.num_subsets());
     685              :                 m_sh.assign_subset( vrt, suse );
     686              :         }
     687              : 
     688              :         suse = m_sh.num_subsets();
     689              : 
     690              :         for( Edge * edg : m_d_cuttingEdges )
     691              :         {
     692              :                 if( edg == nullptr )
     693              :                 {
     694              :                         UG_LOG("NULL UNERLAUBT" << std::endl);
     695              :                         UG_THROW("NULL UNERLAUBT" << std::endl);
     696              :                 }
     697              : 
     698              : //              m_sh.assign_subset( edg, m_sh.num_subsets());
     699              :                 m_sh.assign_subset( edg, suse );
     700              : 
     701              :         }
     702              : 
     703              :         suse = m_sh.num_subsets();
     704              : 
     705              :         for( Face * fac : m_d_crossingNeighboredNotEndingFaces )
     706              :         {
     707              : //              m_sh.assign_subset( fac, m_sh.num_subsets());
     708              :                 m_sh.assign_subset( fac, suse );
     709              :         }
     710              : 
     711              : //      for( Edge * edg : otherEdgeOfCrossingNotEndingFace )
     712              : //      {
     713              : //              if( edg == nullptr )
     714              : //              {
     715              : //                      UG_LOG("NULL C UNERLAUBT" << std::endl);
     716              : //                      UG_THROW("NULL C UNERLAUBT" << std::endl);
     717              : //              }
     718              : //
     719              : //              m_sh.assign_subset( edg, m_sh.num_subsets());
     720              : //
     721              : //      }
     722              :         suse = m_sh.num_subsets();
     723              : 
     724              :         for( Face * fac : m_d_notEndingCrossingFacesNotNeighbour )
     725              :         {
     726              : //              m_sh.assign_subset( fac, m_sh.num_subsets());
     727              :                 m_sh.assign_subset( fac, suse );
     728              :         }
     729              : 
     730              :         suse = m_sh.num_subsets();
     731              : 
     732              :         for( Face * fac : m_d_crossingNeighboredNotEndingFacesCommEdg )
     733              :         {
     734              : //              m_sh.assign_subset( fac, m_sh.num_subsets());
     735              :                 m_sh.assign_subset( fac, suse );
     736              :         }
     737              : 
     738              : //      suse = m_sh.num_subsets();
     739              : //
     740              : //      for( Edge * edg : m_d_allContributingEdges )
     741              : //      {
     742              : //              for( Vertex * vrtOne : m_d_endingCrossingCleftVrtcs )
     743              : //              {
     744              : //                      for( Vertex * vrtTwo : m_d_endingCrossingCleftVrtcs )
     745              : //                      {
     746              : //                              if( vrtOne != vrtTwo )
     747              : //                              {
     748              : //                                      if( EdgeContains(edg, vrtOne) && EdgeContains( edg, vrtTwo) )
     749              : //                                      {
     750              : //                                              UG_LOG("Edge needs to be splitted" << std::endl);
     751              : //
     752              : //                                              m_sh.assign_subset( edg, suse );
     753              : //
     754              : //
     755              : ////                                            vector3 center = CalculateCenter(edg, m_aaPos);
     756              : ////                                            UG_LOG("splitting ECCV edge at " << center << std::endl);
     757              : ////                                            RegularVertex* vrtSE = SplitEdge<RegularVertex>(m_grid, edg, false);
     758              : ////                                            m_aaPos[vrtSE] = center;
     759              : //
     760              : //                                      }
     761              : //                              }
     762              : //                      }
     763              : //
     764              : //              }
     765              : //      }
     766              : 
     767              : 
     768              :         return;
     769              : #endif
     770              : 
     771              : //      return false;
     772            0 : }
     773              : 
     774              : ////////////////////////////////////////////////
     775              : 
     776            0 : bool ArteExpandFracs3D::initialize()
     777              : {
     778              :         UG_LOG("initialize " << std::endl);
     779              : 
     780              :         //      access position attachment
     781            0 :         if(!m_grid.has_vertex_attachment(aPosition) )
     782              :         {
     783              :                 UG_LOG("Error in ExpandFractures Arte 3D: Missing position attachment");
     784            0 :                 return false;
     785              :         }
     786              : 
     787            0 :         m_aaPos = Grid::VertexAttachmentAccessor<APosition>(m_grid, aPosition);
     788              : 
     789              :         //      make sure that the required options are enabled.
     790              : 
     791            0 :         if( ! m_grid.option_is_enabled(VOLOPT_AUTOGENERATE_FACES) )
     792              :         {
     793              :                 UG_LOG("WARNING in Arte 3D init : grid option VOLOPT_AUTOGENERATE_FACES autoenabled.\n");
     794            0 :                 m_grid.enable_options(VOLOPT_AUTOGENERATE_FACES);
     795              :         }
     796              : 
     797            0 :         if( ! m_grid.option_is_enabled(FACEOPT_AUTOGENERATE_EDGES) )
     798              :         {
     799              :                 UG_LOG("WARNING in Arte 3D init: grid option FACEOPT_AUTOGENERATE_EDGES autoenabled.\n");
     800            0 :                 m_grid.enable_options(FACEOPT_AUTOGENERATE_EDGES);
     801              :         }
     802              : 
     803              :         //      vectors that allow to access fracture properties by subset index
     804            0 :         m_fracInfosBySubset = std::vector<FractureInfo>( m_sh.num_subsets(), FractureInfo(-1, -1, 0) );
     805              : 
     806            0 :         for( size_t i = 0; i < m_fracInfos.size(); ++i)
     807              :         {
     808            0 :                 if( m_fracInfos[i].subsetIndex >= m_sh.num_subsets())
     809              :                 {
     810            0 :                         throw(UGError("Bad subsetIndex in given fracInfos."));
     811              :                 }
     812              : 
     813            0 :                 m_fracInfosBySubset[ m_fracInfos[i].subsetIndex] = m_fracInfos[i];
     814              : 
     815              :         }
     816              : 
     817              : 
     818              :         return true;
     819              : }
     820              : 
     821              : 
     822            0 : bool ArteExpandFracs3D::setSelector()
     823              : {
     824              :         //      Collect surrounding volumes, faces and edges of all fractures in a selector
     825              :         //      and select fracture faces, edges and vertices too.
     826              : 
     827              : //      m_sel = Selector(m_grid);
     828              : 
     829            0 :         m_sel.assign_grid(m_grid);
     830              : 
     831            0 :         m_sel.enable_autoselection(false);
     832            0 :         m_sel.enable_selection_inheritance(true);       //required for select and mark, disabled later
     833            0 :         m_sel.enable_strict_inheritance(false);
     834              : 
     835              : //      bool strictInherit = m_sel.strict_inheritance_enabled();
     836              : //
     837              : //      UG_LOG("strikte Inheritenz ist " << strictInherit << " und false ist " << false << std::endl);
     838              : 
     839            0 :         return true;
     840              : }
     841              : 
     842              : 
     843            0 : bool ArteExpandFracs3D::attachMarkers()
     844              : {
     845              :         // first part
     846              : 
     847              :         // attachment pair boundary is fracture, number fractures crossing
     848              : 
     849              :         m_aAdjMarkerVFP = AttVertFracProp();
     850              : 
     851              : //      support::VertexFracturePropertiesVol<IndexType> vfp0; // false, 0 );
     852              :         VertxFracPropts vfp0; // false, 0 );
     853              :         // default value: no boundary fracture, no fractures crossing
     854              : 
     855            0 :         m_grid.attach_to_vertices_dv( m_aAdjMarkerVFP, vfp0 );
     856            0 :         m_aaMarkVrtVFP = Grid::VertexAttachmentAccessor<AttVertFracProp> ( m_grid, m_aAdjMarkerVFP );
     857              : 
     858              :         //m_aAdjMarkerVFP = AttVertFracProp();
     859              :         m_grid.attach_to_edges_dv( m_aAdjMarkerVFP, vfp0 );
     860              : 
     861            0 :         m_aaMarkEdgeVFP = Grid::EdgeAttachmentAccessor<AttVertFracProp>( m_grid, m_aAdjMarkerVFP );
     862              : 
     863              :         m_aAdjMarkerFaceIsFracB = ABool(); // used to know if an face is frac face
     864              : 
     865            0 :         m_grid.attach_to_faces_dv( m_aAdjMarkerFaceIsFracB, false );
     866            0 :         m_aaMarkFaceIsFracB = Grid::FaceAttachmentAccessor<ABool>( m_grid, m_aAdjMarkerFaceIsFracB );
     867              : 
     868              : //      m_aAdjMarkerFaceHasUnclosedFracSideB = ABool();
     869              : //
     870              : //      m_grid.attach_to_faces_dv( m_aAdjMarkerFaceHasUnclosedFracSideB, false );
     871              : //      m_aaMarkFaceHasUnclosedFracSideB = Grid::FaceAttachmentAccessor<ABool>( m_grid, m_aAdjMarkerFaceHasUnclosedFracSideB );
     872              : //
     873              : //      m_aAdjMarkerVrtxHasUnclosedFracB = ABool();
     874              : //
     875              : //      m_grid.attach_to_vertices_dv( m_aAdjMarkerVrtxHasUnclosedFracB, false );
     876              : //      m_aaMarkVrtxHasUnclosedFracB = Grid::VertexAttachmentAccessor<ABool>( m_grid, m_aAdjMarkerVrtxHasUnclosedFracB );
     877              : //
     878              :         m_aAdjMarkerFaceWithEndingCrossingCleft = ABool();
     879              : 
     880            0 :         m_grid.attach_to_faces_dv( m_aAdjMarkerFaceWithEndingCrossingCleft, false );
     881              : 
     882            0 :         m_aaMarkFaceWithEndingCrossingCleft = Grid::FaceAttachmentAccessor<ABool>( m_grid, m_aAdjMarkerFaceWithEndingCrossingCleft );
     883              : 
     884              :         m_aAdjMarkerVrtxAtEndingCrossingCleft = ABool();
     885              : 
     886            0 :         m_grid.attach_to_vertices_dv( m_aAdjMarkerVrtxAtEndingCrossingCleft, false );
     887              : 
     888            0 :         m_aaMarkVrtxAtEndingCrossingCleft = Grid::VertexAttachmentAccessor<ABool>( m_grid, m_aAdjMarkerVrtxAtEndingCrossingCleft );
     889              : //
     890              : //      m_aAdjMarkerVrtx2AtInnerEndOfEndingCrossingFract = ABool();
     891              : //
     892              : //      m_grid.attach_to_vertices_dv( m_aAdjMarkerVrtx2AtInnerEndOfEndingCrossingFract, false );
     893              : //
     894              : //      m_aaMarkVrtx2AtInnerEndOfEndingCrossingFract = Grid::VertexAttachmentAccessor<ABool>( m_grid, m_aAdjMarkerVrtx2AtInnerEndOfEndingCrossingFract );
     895              : 
     896              :         // second part
     897              : 
     898              : //      m_grid.attach_to_volumes(m_attVrtVec);
     899              : //      m_aaVrtVecVol = Grid::VolumeAttachmentAccessor<AttVrtVec>( m_grid, m_attVrtVec);
     900              : 
     901              :         std::vector<Edge*> noEdge;
     902              :         std::vector<Face*> noFace;
     903              : //      std::vector<Volume*> noVol;
     904              : 
     905              :         m_aAdjInfoEdges = AttVecEdge();
     906              :         m_aAdjInfoFaces = AttVecFace();
     907              : //      m_aAdjInfoVols = AttVecVol();
     908              : 
     909            0 :         m_grid.attach_to_vertices_dv( m_aAdjInfoEdges, noEdge );
     910            0 :         m_aaVrtInfoAssoEdges = Grid::VertexAttachmentAccessor<AttVecEdge>( m_grid, m_aAdjInfoEdges );
     911              : 
     912            0 :         m_grid.attach_to_vertices_dv( m_aAdjInfoFaces, noFace );
     913            0 :         m_aaVrtInfoAssoFaces = Grid::VertexAttachmentAccessor<AttVecFace>( m_grid, m_aAdjInfoFaces );
     914              : 
     915              : //      m_grid.attach_to_vertices_dv( m_aAdjInfoVols, noVol );
     916              : //      m_aaVrtInfoAssoVols = Grid::VertexAttachmentAccessor<AttVecVol>( m_grid, m_aAdjInfoVols );
     917              : 
     918              : 
     919              :         //  TODO FIXME
     920              :         //  das fehlt hier , Analogon 2D Fall!!!!!!!!!!!!! der geht hier eigentlich weiter
     921              :         // die Vertizes, Faces und Edges, die mit einer Kluft zu tun haben
     922              :         //      using VertFracTrip = VertexFractureTriple<Edge*, Face*, vector3>;
     923              :         //      using VecVertFracTrip = std::vector<VertFracTrip>;
     924              :         //      VecVertFracTrip vertexNoInfo;
     925              : 
     926              :         // AttVecVertFracTrip m_aAdjInfoAVVFT;
     927              : 
     928              : //      VecVertFracTrip vertexNoInfo;
     929              : //
     930              : //      m_aAdjInfoAVVFT = AttVecVertFracTrip();
     931              : //
     932              : //      m_grid.attach_to_vertices_dv( m_aAdjInfoAVVFT, vertexNoInfo );
     933              : //
     934              : //      m_aaVrtInfoFraTri = Grid::VertexAttachmentAccessor<AttVecVertFracTrip>(m_grid,  m_aAdjInfoAVVFT );
     935              : 
     936              : 
     937              :         //      associate a vector of vertices for each volume adjacent to the frac.
     938              :         //      An entry later will contain the new vertex, if the
     939              :         //      corresponding vertex is an inner fracture vertex, and nullptr if not.
     940              : 
     941              :         m_attVrtVec = AttVrtVec();
     942              : 
     943            0 :         m_grid.attach_to_volumes(m_attVrtVec);
     944              : 
     945            0 :         m_aaVrtVecVol = Grid::VolumeAttachmentAccessor<AttVrtVec>(m_grid, m_attVrtVec);
     946              : 
     947              : 
     948              : //      VecAttachedVolumeElemInfo noVolInfo;
     949              : 
     950              : //      m_aAdjVolElmInfo = AttVecAttachedVolumeElemInfo();
     951              : //
     952              : //      m_grid.attach_to_vertices_dv(m_aAdjVolElmInfo,noVolInfo);
     953              : //
     954              : //      m_aaVolElmInfo = Grid::VertexAttachmentAccessor<AttVecAttachedVolumeElemInfo>(m_grid, m_aAdjVolElmInfo);
     955              : 
     956              : 
     957              :         VecSegmentVolElmInfo noSegmts;
     958              : 
     959              :         m_attAdjVecSegVolElmInfo = AttVecSegmentVolElmInfo();
     960              : 
     961            0 :         m_grid.attach_to_vertices_dv( m_attAdjVecSegVolElmInfo, noSegmts );
     962              : 
     963            0 :         m_accsAttVecSegVolElmInfo = Grid::VertexAttachmentAccessor<AttVecSegmentVolElmInfo>( m_grid, m_attAdjVecSegVolElmInfo );
     964              : 
     965              :         VecSegmentLimitingSides emptyVecSegmLimSid;
     966              : 
     967              :         AttVecSegmLimSid m_attVecSegmLimSid;
     968              : 
     969              :         m_grid.attach_to_vertices_dv( m_attVecSegmLimSid, emptyVecSegmLimSid );
     970              : 
     971            0 :         m_vrtxAttAccsVecSegmLimSid = Grid::VertexAttachmentAccessor<AttVecSegmLimSid>( m_grid, m_attVecSegmLimSid );
     972              : 
     973              :         VecEndingCrossingFractureSegmentInfo emptyVECFSI;
     974              : 
     975              :         m_attAtVrtxVecEndingCrossFractSegmInfo = AttVecEndingCrossingFractureSegmentInfo();
     976              : 
     977            0 :         m_grid.attach_to_vertices_dv( m_attAtVrtxVecEndingCrossFractSegmInfo, emptyVECFSI );
     978              : 
     979            0 :         m_vrtxAttAccsVecEndingCrossFractSegmInfo = Grid::VertexAttachmentAccessor<AttVecEndingCrossingFractureSegmentInfo>( m_grid, m_attAtVrtxVecEndingCrossFractSegmInfo );
     980              : 
     981              : //      m_attAtVrtxIfVrtxIsEndingCrossingCleftVrtx = ABool();
     982              : //
     983              : //      m_grid.attach_to_vertices_dv( m_attAtVrtxIfVrtxIsEndingCrossingCleftVrtx, false );
     984              : //
     985              : //      m_vrtxAttAccsVrtxIsEndingCrossingCleftVrtx = Grid::VertexAttachmentAccessor<ABool>( m_grid, m_attAtVrtxIfVrtxIsEndingCrossingCleftVrtx );
     986              : 
     987              :         m_attAtFaceIfFaceIsSegmLimFaceEndingCrossingCleft = ABool();
     988              : 
     989            0 :         m_grid.attach_to_faces_dv( m_attAtFaceIfFaceIsSegmLimFaceEndingCrossingCleft, false );
     990              : 
     991            0 :         m_facAttAccsIfFaceIsSegmLimFaceEndingCrossingCleft = Grid::FaceAttachmentAccessor<ABool>( m_grid, m_attAtFaceIfFaceIsSegmLimFaceEndingCrossingCleft );
     992              : 
     993              :         m_attAtVolIfVolTouchesEndingCrossingCleft = ABool();
     994              : 
     995            0 :         m_grid.attach_to_volumes_dv( m_attAtVolIfVolTouchesEndingCrossingCleft, false );
     996              : 
     997            0 :         m_volAttAccsVolTouchesEndingCrossingCleft = Grid::VolumeAttachmentAccessor<ABool>( m_grid, m_attAtVolIfVolTouchesEndingCrossingCleft );
     998              : 
     999              :         m_attAtVrtxIfVrtxArisesFromExpandedEndingCrossingCleft = ABool();
    1000              : 
    1001            0 :         m_grid.attach_to_vertices_dv( m_attAtVrtxIfVrtxArisesFromExpandedEndingCrossingCleft, false );
    1002              : 
    1003            0 :         m_vrtxAttAccsVrtxArisesFromExpandedEndingCrossingCleft = Grid::VertexAttachmentAccessor<ABool>( m_grid, m_attAtVrtxIfVrtxArisesFromExpandedEndingCrossingCleft );
    1004              : 
    1005            0 :         return true;
    1006            0 : }
    1007              : 
    1008              : 
    1009            0 : bool ArteExpandFracs3D::detachMarkers()
    1010              : {
    1011            0 :         m_grid.detach_from_vertices( m_aAdjMarkerVFP );
    1012            0 :         m_grid.detach_from_edges( m_aAdjMarkerVFP );
    1013            0 :         m_grid.detach_from_faces( m_aAdjMarkerFaceIsFracB );
    1014              : //      m_grid.detach_from_faces( m_aAdjMarkerFaceHasUnclosedFracSideB );
    1015              : //
    1016              : //      m_grid.detach_from_vertices( m_aAdjMarkerVrtxHasUnclosedFracB );
    1017              : //
    1018            0 :         m_grid.detach_from_faces( m_aAdjMarkerFaceWithEndingCrossingCleft );
    1019            0 :         m_grid.detach_from_vertices( m_aAdjMarkerVrtxAtEndingCrossingCleft );
    1020              : //      m_grid.detach_from_vertices( m_aAdjMarkerVrtx2AtInnerEndOfEndingCrossingFract );
    1021              : 
    1022            0 :         m_grid.detach_from_vertices( m_aAdjInfoEdges );
    1023            0 :         m_grid.detach_from_vertices( m_aAdjInfoFaces );
    1024              : //      m_grid.detach_from_vertices( m_aAdjInfoVols );
    1025              : 
    1026              : //      m_grid.detach_from_vertices( m_aAdjInfoAVVFT  );
    1027              : 
    1028            0 :         m_grid.detach_from_volumes( m_attVrtVec );
    1029              : 
    1030              : //      m_grid.detach_from_vertices(m_aAdjVolElmInfo);
    1031              : 
    1032            0 :         m_grid.detach_from_vertices( m_attAdjVecSegVolElmInfo );
    1033              : 
    1034            0 :         m_grid.detach_from_vertices( m_attVecSegmLimSid );
    1035              : 
    1036            0 :         m_grid.detach_from_vertices( m_attAtVrtxVecEndingCrossFractSegmInfo );
    1037              : 
    1038              : //      m_grid.detach_from_vertices( m_attAtVrtxIfVrtxIsEndingCrossingCleftVrtx );
    1039              : 
    1040            0 :         m_grid.detach_from_faces( m_attAtFaceIfFaceIsSegmLimFaceEndingCrossingCleft );
    1041              : 
    1042            0 :         m_grid.detach_from_volumes( m_attAtVolIfVolTouchesEndingCrossingCleft );
    1043              : 
    1044            0 :         m_grid.detach_from_vertices( m_attAtVrtxIfVrtxArisesFromExpandedEndingCrossingCleft );
    1045              : 
    1046            0 :         return true;
    1047              : }
    1048              : 
    1049            0 : bool ArteExpandFracs3D::enableVolOptAutoGenFac()
    1050              : {
    1051              :         // brauchen wir das? für was? von SR irgendwie übernommen, wo dort was entfernt ähnliches gemacht wird....
    1052            0 :         if(! m_grid.option_is_enabled(VOLOPT_AUTOGENERATE_FACES) )
    1053              :         {
    1054              :                 UG_LOG("WARNING grid option VOLOPT_AUTOGENERATE_FACES autoenabled.\n");
    1055            0 :                 m_grid.enable_options(VOLOPT_AUTOGENERATE_FACES);
    1056            0 :                 return true;
    1057              :         }
    1058              : 
    1059              :         return false;
    1060              : 
    1061              : }
    1062              : 
    1063              : //////////////////////////////////////////////////////////////////
    1064              : 
    1065            0 : int ArteExpandFracs3D::splitInnerFreeFracEdgs()
    1066              : {
    1067              :         int splittedEdges = 0;
    1068              : 
    1069            0 :         for(size_t i_fi = 0; i_fi < m_fracInfos.size(); ++i_fi )
    1070              :         {
    1071            0 :                 int fracIndSudo = m_fracInfos[i_fi].subsetIndex;
    1072              : 
    1073            0 :                 UG_LOG("sudo ind " << fracIndSudo << std::endl);
    1074              : 
    1075              :                 AttVertFracProp func_aAdjMarkerVFP;
    1076              :                 VertxFracPropts vfp0;
    1077            0 :                 m_grid.attach_to_edges_dv( func_aAdjMarkerVFP, vfp0 );
    1078            0 :                 Grid::EdgeAttachmentAccessor<AttVertFracProp> func_aaMarkEdgeVFP( m_grid, func_aAdjMarkerVFP );
    1079              : 
    1080            0 :                 for( FaceIterator iter = m_sh.begin<Face>(fracIndSudo); iter != m_sh.end<Face>(fracIndSudo); ++iter )
    1081              :                 {
    1082              :                         Face* fac = *iter;
    1083              : 
    1084              :                         std::vector<Edge*> facEdges;
    1085              : 
    1086            0 :                         CollectEdges( facEdges, m_grid, fac );
    1087              : 
    1088            0 :                         for( auto const & edg : facEdges )
    1089              :                         {
    1090            0 :                                 if( func_aaMarkEdgeVFP[edg].getNumberFracEdgesInVertex() != 0 )
    1091            0 :                                         UG_THROW("Attachment nicht auf default " << std::endl);
    1092              : //                              func_aaMarkEdgeVFP[edg].setNumberCrossingFracsInVertex(0);
    1093              :                         }
    1094            0 :                 }
    1095              : 
    1096              : 
    1097            0 :                 for( FaceIterator iter = m_sh.begin<Face>(fracIndSudo); iter != m_sh.end<Face>(fracIndSudo); ++iter )
    1098              :                 {
    1099              :                         Face* fac = *iter;
    1100              : 
    1101              :                         std::vector<Edge*> facEdges;
    1102              : 
    1103            0 :                         CollectEdges( facEdges, m_grid, fac );
    1104              : 
    1105            0 :                         for( auto const & edg : facEdges )
    1106              :                         {
    1107            0 :                                 func_aaMarkEdgeVFP[edg]++;
    1108              :                         }
    1109            0 :                 }
    1110              : 
    1111              :                 std::vector<Edge *> edgesToBeSplitted;
    1112              : 
    1113            0 :                 for( FaceIterator iter = m_sh.begin<Face>(fracIndSudo); iter != m_sh.end<Face>(fracIndSudo); ++iter )
    1114              :                 {
    1115              :                         Face* fac = *iter;
    1116              : 
    1117              :                         std::vector<Edge*> facEdges;
    1118              : 
    1119            0 :                         CollectEdges( facEdges, m_grid, fac );
    1120              : 
    1121              :                         IndexType openEdges = 0;
    1122              : 
    1123            0 :                         for( auto const & edg : facEdges )
    1124              :                         {
    1125            0 :                                 VertxFracPropts & edgeFracPrps = func_aaMarkEdgeVFP[edg];
    1126              : 
    1127              :                                 IndexType fracEdgesOverlap = edgeFracPrps.getNumberFracEdgesInVertex();
    1128              : 
    1129            0 :                                 if( fracEdgesOverlap == 1 )
    1130              :                                 {
    1131            0 :                                         openEdges++;
    1132              :                                 }
    1133            0 :                                 else if( fracEdgesOverlap == 2 )
    1134              :                                 {
    1135              :                                         ; // fine, inner edge of fracture
    1136              :                                 }
    1137              :                                 else
    1138              :                                 {
    1139            0 :                                         m_sh.assign_subset(edg, m_sh.num_subsets());
    1140              : 
    1141              :                                         UG_LOG("how many fractures at this edge " << fracEdgesOverlap << std::endl);
    1142            0 :                                         UG_LOG("sudo " << fracIndSudo << std::endl);
    1143            0 :                                         UG_THROW("how many fractures at this edge " << fracEdgesOverlap << std::endl);
    1144              :                                         UG_THROW("sudo " << fracIndSudo << std::endl);
    1145              : //                                      return splittedEdges;
    1146              : //                                      UG_THROW("how many fractures at this edge " << fracEdgesOverlap << std::endl);
    1147              :                                 }
    1148              :                         }
    1149              : 
    1150            0 :                         if( openEdges == 2 )
    1151              :                         {
    1152              :                                 // figure out that edge that is not open, this must be splitted
    1153              : 
    1154              :                                 IndexType innerEdges = 0;
    1155              : 
    1156            0 :                                 for( auto const & edg : facEdges )
    1157              :                                 {
    1158            0 :                                         VertxFracPropts & edgeFracPrps = func_aaMarkEdgeVFP[edg];
    1159              : 
    1160              :                                         IndexType fracEdgesOverlap = edgeFracPrps.getNumberFracEdgesInVertex();
    1161              : 
    1162            0 :                                         if( fracEdgesOverlap == 2 )
    1163              :                                         {
    1164            0 :                                                 edgesToBeSplitted.push_back(edg);
    1165            0 :                                                 innerEdges++;
    1166              :                                         }
    1167              :                                 }
    1168              : 
    1169            0 :                                 if( innerEdges != 1 )
    1170              :                                 {
    1171              :                                         UG_LOG("inner edge number strange " << innerEdges << std::endl);
    1172            0 :                                         UG_THROW("inner edge number strange " << innerEdges << std::endl);
    1173              :                                 }
    1174              : 
    1175              : 
    1176              :                         }
    1177            0 :                 }
    1178              : 
    1179            0 :                 for( Edge * edg : edgesToBeSplitted )
    1180              :                 {
    1181            0 :                         vector3 center = CalculateCenter(edg, m_aaPos);
    1182            0 :                         UG_LOG("splitting edge at " << center << std::endl);
    1183            0 :                         RegularVertex* vrt = SplitEdge<RegularVertex>(m_grid, edg, false);
    1184              :                         m_aaPos[vrt] = center;
    1185            0 :                         splittedEdges++;
    1186              :                 }
    1187              : 
    1188            0 :                 m_grid.detach_from_edges( func_aAdjMarkerVFP );
    1189            0 :         }
    1190              : 
    1191            0 :         return splittedEdges;
    1192              : }
    1193              : 
    1194              : #if 0
    1195              : int ArteExpandFracs3D::splitInnerFreeFracEdgs()
    1196              : {
    1197              :         int splittedEdges = 0;
    1198              : 
    1199              :         UG_LOG("search inner frac edges with two inner boundary edges" << std::endl);
    1200              : 
    1201              :         // TODO FIXME
    1202              : 
    1203              : 
    1204              :         for(size_t i_fi = 0; i_fi < m_fracInfos.size(); ++i_fi )
    1205              :         {
    1206              :                 int fracIndSudo = m_fracInfos[i_fi].subsetIndex;
    1207              : 
    1208              :                 UG_LOG("sudo ind " << fracIndSudo << std::endl);
    1209              : 
    1210              : //              std::vector<Edge *> edgesToBeSplitted;
    1211              : 
    1212              :                 std::vector<Face*> facesAtInnerBoundary;
    1213              : 
    1214              :                 for( FaceIterator iter = m_sh.begin<Face>(fracIndSudo); iter != m_sh.end<Face>(fracIndSudo); ++iter )
    1215              :                 {
    1216              :                         Face* fac = *iter;
    1217              : 
    1218              : //                      std::vector<Vertex*> assoVrt;
    1219              : //
    1220              : //                      CollectVertices( assoVrt, m_grid, fac );
    1221              : //
    1222              : //                      // check number of edges which have only one fracture face around
    1223              : //
    1224              : //                      for( Vertex * vrt : assoVrt )
    1225              : //                      {
    1226              :                         std::vector<Edge*> assoEdg;
    1227              : 
    1228              :                         CollectEdges( assoEdg, m_grid, fac );
    1229              : 
    1230              :                         for( Edge * edg : assoEdg )
    1231              :                         {
    1232              :                                 // check if edge is inner boundary edge, i.e. if has at one side non-fracture face
    1233              :                                 // only check for those edges which have one fracture face on one side
    1234              : 
    1235              :                                 // split only inner edges at the moment in case of problems
    1236              :                                 if( IsBoundaryEdge3D(m_grid, edg) )
    1237              :                                 {
    1238              :                                         continue;
    1239              :                                 }
    1240              : 
    1241              :                                 std::vector<Face *> assoFac;
    1242              : 
    1243              :                                 CollectFaces( assoFac, m_grid, edg );
    1244              : 
    1245              :                                 IndexType numFacsFromFracSudo = 0;
    1246              : 
    1247              :                                 for( Face * testFac : assoFac )
    1248              :                                 {
    1249              :                                         IndexType testSudo = m_sh.get_subset_index(testFac);
    1250              : 
    1251              :                                         if( testSudo == fracIndSudo )
    1252              :                                                 numFacsFromFracSudo++;
    1253              :                                 }
    1254              : 
    1255              :                                 if( numFacsFromFracSudo == 0 )
    1256              :                                 {
    1257              : //                                      UG_LOG("no facs at edg " << std::endl );
    1258              :                                                 ; // nothing to do, belongs from an edge not relevant for the fracture
    1259              :                                 }
    1260              :                                 else if( numFacsFromFracSudo == 1 )
    1261              :                                 {
    1262              :                                         // relevant! edge needs to be split
    1263              : 
    1264              : //                                      UG_LOG("one fac at edg" << std::endl);
    1265              : 
    1266              :                                         addElem( facesAtInnerBoundary, fac );
    1267              :                                 }
    1268              :                                 else if( numFacsFromFracSudo == 2 )
    1269              :                                 {
    1270              : //                                              UG_LOG("two fac sides at edge " << std::endl);
    1271              :                                                 ; // nothing to do, edge at both sides surrounded by fracture face
    1272              :                                 }
    1273              :                                 else
    1274              :                                 {
    1275              :                                         UG_LOG("komische Ecke" << std::endl);
    1276              :                                         UG_THROW("komische Ecke" << std::endl);
    1277              :                                 }
    1278              :                         }
    1279              : 
    1280              :                 }
    1281              : 
    1282              :                 std::vector<Edge *> edgesToBeSplitted;
    1283              : 
    1284              :                 for( Face * fac : facesAtInnerBoundary )
    1285              :                 {
    1286              :                         std::vector<Vertex *> assoVrt;
    1287              : 
    1288              :                         CollectVertices(assoVrt, m_grid, fac);
    1289              : 
    1290              :                         // check if at a vertex of a frac face is associated with two inner boundary edges
    1291              : 
    1292              :                         for( Vertex * vrt : assoVrt )
    1293              :                         {
    1294              :                                 std::vector<Edge*> assoEdg;
    1295              : 
    1296              :                                 CollectEdges( assoEdg, m_grid, vrt );
    1297              : 
    1298              :                                 IndexType innerBoundaryEdges = 0;
    1299              : 
    1300              :                                 // count number of edges of the vertex which have one free side
    1301              : 
    1302              :                                 for( Edge * edg : assoEdg )
    1303              :                                 {
    1304              :                                         // check if edge is inner boundary edge, i.e. if has at one side non-fracture face
    1305              :                                         // only check for those edges which have one fracture face on one side
    1306              : 
    1307              :                                         // split only inner edges at the moment in case of problems
    1308              :                                         if( IsBoundaryEdge3D(m_grid, edg) )
    1309              :                                         {
    1310              :                                                 continue;
    1311              :                                         }
    1312              : 
    1313              :                                         std::vector<Face *> assoFac;
    1314              : 
    1315              :                                         CollectFaces( assoFac, m_grid, edg );
    1316              : 
    1317              :                                         IndexType numFacsFromFracSudo = 0;
    1318              : 
    1319              :                                         for( Face * testFac : assoFac )
    1320              :                                         {
    1321              :                                                 IndexType testSudo = m_sh.get_subset_index(testFac);
    1322              : 
    1323              :                                                 if( testSudo == fracIndSudo )
    1324              :                                                         numFacsFromFracSudo++;
    1325              :                                         }
    1326              : 
    1327              :                                         if( numFacsFromFracSudo == 0 )
    1328              :                                         {
    1329              : //                                              UG_LOG("no facs at edg " << std::endl );
    1330              :                                                 ; // nothing to do, belongs from an edge not relevant for the fracture
    1331              :                                         }
    1332              :                                         else if( numFacsFromFracSudo == 1 )
    1333              :                                         {
    1334              :                                                 // relevant! edge needs to be split
    1335              : 
    1336              : //                                              UG_LOG("one fac at edg" << std::endl);
    1337              : 
    1338              : //                                              addElemToSplit( edgesToBeSplitted, edg );
    1339              :                                                 innerBoundaryEdges++;
    1340              :                                         }
    1341              :                                         else if( numFacsFromFracSudo == 2 )
    1342              :                                         {
    1343              : //                                              UG_LOG("two fac sides at edge " << std::endl);
    1344              :                                                 ; // nothing to do, edge at both sides surrounded by fracture face
    1345              :                                         }
    1346              :                                         else
    1347              :                                         {
    1348              :                                                 UG_LOG("komische Ecke" << std::endl);
    1349              :                                                 UG_THROW("komische Ecke" << std::endl);
    1350              :                                         }
    1351              : 
    1352              :                                 }
    1353              : 
    1354              :                                 if( innerBoundaryEdges == 0  || 1 || 3 )
    1355              :                                 {
    1356              : //                                      UG_LOG("komische innere Grenze ohne Grenze " << std::endl);
    1357              : //                                      UG_THROW("komische innere Grenze ohne Grenze " << std::endl);
    1358              : //                                      ; // nothing to do
    1359              : //                              }
    1360              : //                              else if( innerBoundaryEdges == 1 )
    1361              : //                              {
    1362              :                                         ; // nothing to do, entire boundary edge with no problem, or external edge
    1363              :                                 }
    1364              :                                 else if( innerBoundaryEdges == 2 )
    1365              :                                 {
    1366              :                                         // figure out that edge that is NOT the boundary edge
    1367              : 
    1368              :                                         UG_LOG("we have two inner boundary edges" << std::endl);
    1369              : 
    1370              :                                         std::vector<Edge*> assoEdg;
    1371              : 
    1372              :                                         CollectEdges( assoEdg, m_grid, fac );
    1373              : 
    1374              :                                         for( Edge * edg : assoEdg )
    1375              :                                         {
    1376              :                                                 // check if edge is inner boundary edge, i.e. if has at one side non-fracture face
    1377              :                                                 // only check for those edges which have one fracture face on one side
    1378              : 
    1379              :                                                 // split only inner edges at the moment in case of problems
    1380              :                                                 if( IsBoundaryEdge3D(m_grid, edg) )
    1381              :                                                 {
    1382              :                                                         continue;
    1383              :                                                 }
    1384              : 
    1385              :                                                 std::vector<Face *> assoFac;
    1386              : 
    1387              :                                                 CollectFaces( assoFac, m_grid, edg );
    1388              : 
    1389              :                                                 IndexType numFacsFromFracSudo = 0;
    1390              : 
    1391              :                                                 for( Face * testFac : assoFac )
    1392              :                                                 {
    1393              :                                                         IndexType testSudo = m_sh.get_subset_index(testFac);
    1394              : 
    1395              :                                                         if( testSudo == fracIndSudo )
    1396              :                                                                 numFacsFromFracSudo++;
    1397              :                                                 }
    1398              : 
    1399              :                                                 if( numFacsFromFracSudo == 0 ||  numFacsFromFracSudo == 1 )
    1400              :                                                 {
    1401              :                                                         // relevant! edge needs to be split
    1402              : 
    1403              :                 //                                      UG_LOG("one fac at edg" << std::endl);
    1404              :                                                         ;
    1405              : //                                                      addElem( facesAtInnerBoundary, fac );
    1406              :                                                 }
    1407              :                                                 else if( numFacsFromFracSudo == 2 )
    1408              :                                                 {
    1409              :                 //                                              UG_LOG("two fac sides at edge " << std::endl);
    1410              :                                                                 ; // nothing to do, edge at both sides surrounded by fracture face
    1411              :                                                                 addElem(edgesToBeSplitted, edg);
    1412              :                                                 }
    1413              :                                                 else
    1414              :                                                 {
    1415              :                                                         UG_LOG("komische Ecke" << std::endl);
    1416              :                                                         UG_THROW("komische Ecke" << std::endl);
    1417              :                                                 }
    1418              :                                         }
    1419              : 
    1420              :                                 }
    1421              :                                 else
    1422              :                                 {
    1423              :                                         UG_LOG("how many inner boundary edges at a fracture face???" << std::endl) ;
    1424              :                                         UG_THROW("how many inner boundary edges at a fracture face???" << std::endl) ;
    1425              :                                 }
    1426              :                         }
    1427              : 
    1428              :                         // figure out that edge that needs to be splitted - it is that one which is in touch with the fracture on two sides
    1429              : 
    1430              : //                      for( Face * fac : facesAtInnerBoundary )
    1431              : 
    1432              : 
    1433              : 
    1434              :                 }
    1435              : 
    1436              :                 for( Edge * edg : edgesToBeSplitted )
    1437              :                 {
    1438              :                         vector3 center = CalculateCenter(edg, m_aaPos);
    1439              :                         UG_LOG("splitting edge at " << center << std::endl);
    1440              :                         RegularVertex* vrt = SplitEdge<RegularVertex>(m_grid, edg, false);
    1441              :                         m_aaPos[vrt] = center;
    1442              :                 }
    1443              : 
    1444              :         }
    1445              : 
    1446              : 
    1447              :         return splittedEdges;
    1448              : 
    1449              : }
    1450              : 
    1451              : #endif
    1452              : 
    1453              : //////////////////////////////////////////////////////////////////
    1454              : 
    1455              : template<typename ELEMTYP>
    1456              : bool ArteExpandFracs3D::addElem(std::vector<ELEMTYP> & knownElems, ELEMTYP elemToAdd )
    1457              : {
    1458            0 :         return support::addElem(knownElems, elemToAdd);
    1459              : 
    1460              : //      bool unknown = true;
    1461              : //
    1462              : //      for( ELEMTYP elmKnown : knownElems )
    1463              : //      {
    1464              : //              if( elemToAdd == elmKnown )
    1465              : //              {
    1466              : //                      unknown = false;
    1467              : //                      break;
    1468              : //              }
    1469              : //      }
    1470              : //
    1471              : //      if( unknown )
    1472              : //              knownElems.push_back(elemToAdd);
    1473              : //
    1474              : //      return unknown;
    1475              : 
    1476              : }
    1477              : 
    1478              : //////////////////////////////////////////////////////////////////
    1479              : 
    1480              : 
    1481            0 : bool ArteExpandFracs3D::countAndSelectFracBaseNums()
    1482              : {
    1483              :         UG_LOG("countandselect" << std::endl);
    1484              : 
    1485            0 :         for(size_t i_fi = 0; i_fi < m_fracInfos.size(); ++i_fi )
    1486              :         {
    1487            0 :                 int fracIndSudo = m_fracInfos[i_fi].subsetIndex;
    1488              : 
    1489            0 :                 UG_LOG("sudo ind " << fracIndSudo << std::endl);
    1490              : 
    1491            0 :                 for( FaceIterator iter = m_sh.begin<Face>(fracIndSudo); iter != m_sh.end<Face>(fracIndSudo); ++iter )
    1492              :                 {
    1493              :                         Face* fac = *iter;
    1494              : 
    1495              : //                      UG_LOG("Gesicht " << m_aaPos[fac] << std::endl);
    1496              : 
    1497            0 :                         vector3 facCenter = CalculateCenter( fac, m_aaPos );
    1498            0 :                         UG_LOG("fac center " << facCenter << std::endl);
    1499              : 
    1500            0 :                         for( IndexType i = 0; i < fac->num_vertices(); i++ )
    1501            0 :                                 UG_LOG("Vertex " << i << " -> " << m_aaPos[fac->vertex(i)] << std::endl);
    1502              : 
    1503              :                         UG_LOG("alle Vertizes" << std::endl);
    1504              : 
    1505            0 :                         m_sel.select(fac);
    1506              : 
    1507              :                         UG_LOG("selektiert msel " << fac << std::endl);
    1508              : 
    1509              :                         m_aaMarkFaceIsFracB[fac] = true;
    1510              : 
    1511              :                         UG_LOG("mark bool " << fac << std::endl);
    1512              : 
    1513              : //                      return true;
    1514              : 
    1515              :                         std::vector<Edge*> facEdges;
    1516              : 
    1517              :                         UG_LOG("kollektiere ecken" << std::endl);
    1518              : 
    1519            0 :                         CollectEdges( facEdges, m_grid, fac );
    1520              : 
    1521            0 :                         IndexType d_anzahlEcken = facEdges.size();
    1522              : 
    1523            0 :                         if( d_anzahlEcken == 0 )
    1524              :                         {
    1525              :                                 UG_LOG("keine Ecken " << std::endl);
    1526              :                                 return true;
    1527              :                         }
    1528              : 
    1529              :                         UG_LOG("Anzahl Ecken " << d_anzahlEcken << std::endl);
    1530              : 
    1531            0 :                         for( auto const & edg : facEdges )
    1532              :                         {
    1533            0 :                                 m_aaMarkEdgeVFP[edg]++;
    1534              : 
    1535            0 :                                 if( IsBoundaryEdge3D( m_grid, edg ) )
    1536            0 :                                         m_aaMarkEdgeVFP[edg].setIsBndFracVertex();
    1537              : 
    1538            0 :                                 m_sel.select(edg);
    1539              :                         }
    1540              : 
    1541              :                         UG_LOG("Ecken gesammelt " << std::endl);
    1542              : 
    1543            0 :                         for(size_t i = 0; i < fac->num_vertices(); ++i)
    1544              :                         {
    1545            0 :                                 Vertex* vrt = fac->vertex(i);
    1546              :                                 m_sel.select(vrt);
    1547              :                                 // TODO FIXME hier anpassen, herausfinden ob fracture geschlossen
    1548              :                                 // oder inneres Ende, und Anzahl der umgebenden fractures bestimmen!!!
    1549              : 
    1550              :                                 auto & vrtxFracPrps = m_aaMarkVrtVFP[ vrt ];
    1551              : 
    1552              : //                              m_aaMarkVrtVFP[vrt]++;
    1553              :                                 vrtxFracPrps++;
    1554              :                                 // vielleicht auch in nachfolgendem Loop über alle selektierten Vertizes,
    1555              :                                 // wo dann die attached faces abgelaufen und dabei die Subdomain Nummer ermittelt wird
    1556              :                                 // kann eventuell sogar im Hauptloop gemacht werden, dann könnte man praktisch
    1557              :                                 // das alte vertex fracture properties von 2D weiter verwenden, noch zu klären
    1558              : 
    1559              : //                              m_aaMarkVrtVFP[vrt].addFractSudo(fracIndSudo);
    1560            0 :                                 vrtxFracPrps.addFractSudo(fracIndSudo);
    1561              : 
    1562            0 :                                 if( IsBoundaryVertex3D(m_grid, vrt) )
    1563              :                                 {
    1564              : //                                      m_aaMarkVrtVFP[vrt].setIsBndFracVertex();
    1565              :                                         vrtxFracPrps.setIsBndFracVertex();
    1566              :                                 }
    1567              : 
    1568              :                                 // nicht mehr notwendig
    1569              : //                              // die Ecken heraus filtern, die mit diesem Vertex assoziert sind
    1570              : //                              std::vector<Edge*> attEdg;
    1571              : //
    1572              : //                              for( auto const & ae: facEdges )
    1573              : //                              {
    1574              : //                                      if( EdgeContains(ae,vrt) )
    1575              : //                                              attEdg.push_back(ae);
    1576              : //                              }
    1577              : //
    1578              : //                              if( attEdg.size() == 2 )
    1579              : //                              {
    1580              : //                                      EdgePair edgPr( attEdg[0], attEdg[1] );
    1581              : //
    1582              : //                                      AttachedFractFaceEdgeSudo afes( fac, edgPr, fracIndSudo );
    1583              : //
    1584              : //                                      vrtxFracPrps.addAttachedFractElem(afes);
    1585              : //                              }
    1586              : //                              else
    1587              : //                              {
    1588              : //                                      UG_THROW("number of attached edges wrong " << std::endl);
    1589              : //                              }
    1590              : 
    1591              :                         }
    1592            0 :                 }
    1593              :         }
    1594              : 
    1595              : 
    1596              :         //      now make sure that no inner edge is associated with two
    1597              :         //      boundary vertices (referring to the selection)
    1598              : 
    1599              :         constexpr bool splitEdgesTwoBdryVrt = false;
    1600              : 
    1601              :         if( splitEdgesTwoBdryVrt )
    1602              :         {
    1603              :                 std::vector<Edge*> tmpEdges;
    1604              : 
    1605              :                 for(EdgeIterator iterEdg = m_sel.begin<Edge>(); iterEdg != m_sel.end<Edge>(); iterEdg++ )
    1606              :                 {
    1607              :                         Edge* edg = *iterEdg;
    1608              : 
    1609              :                         Vertex * vrtZer = edg->vertex(0);
    1610              :                         Vertex * vrtOne = edg->vertex(1);
    1611              : 
    1612              :                         VertxFracPropts & vrtxFracPrpsVrtZer = m_aaMarkVrtVFP[ vrtZer ];
    1613              :                         VertxFracPropts & vrtxFracPrpsVrtOne = m_aaMarkVrtVFP[ vrtOne ];
    1614              :                         VertxFracPropts & edgeFracPrps = m_aaMarkEdgeVFP[ edg ];
    1615              : 
    1616              :                         if(      vrtxFracPrpsVrtZer.getIsBndFracVertex()
    1617              :                                 &&   vrtxFracPrpsVrtOne.getIsBndFracVertex()
    1618              :                                 && ! edgeFracPrps.getIsBndFracVertex()
    1619              :                         )
    1620              :                         {
    1621              :                                 tmpEdges.push_back(edg);
    1622              :                         }
    1623              : 
    1624              :                 }
    1625              : 
    1626              :                 for( Edge * edg : tmpEdges )
    1627              :                 {
    1628              :                         vector3 center = CalculateCenter(edg, m_aaPos);
    1629              :                         RegularVertex* vrt = SplitEdge<RegularVertex>(m_grid, edg, false);
    1630              :                         m_aaPos[vrt] = center;
    1631              :                         m_sel.select(vrt);
    1632              :                         auto & vrtxFracPrps = m_aaMarkVrtVFP[ vrt ];
    1633              :                         vrtxFracPrps++;
    1634              : 
    1635              :                         vrtxFracPrps.setIsBndFracVertex(false);
    1636              : 
    1637              :                         //      assign adjacency values for associated selected edges (2 to each)
    1638              :                         for(Grid::AssociatedEdgeIterator iterEdg  = m_grid.associated_edges_begin(vrt);
    1639              :                                                                                          iterEdg != m_grid.associated_edges_end(vrt);
    1640              :                                                                                          iterEdg++
    1641              :                         )
    1642              :                         {
    1643              :                                 Edge * assoEdg = *iterEdg;
    1644              : 
    1645              :                                 if( m_sel.is_selected(assoEdg) )
    1646              :                                 {
    1647              :                                         auto & edgFracPrps = m_aaMarkEdgeVFP[assoEdg];
    1648              :                                         edgFracPrps.setIsBndFracVertex(false);
    1649              :                                 }
    1650              :                         }
    1651              :                 }
    1652              : 
    1653              :                 // TODO FIXME unsicher, ob das hier richtig übertragen von Prof. Reiter......
    1654              :         }
    1655              : 
    1656              : #if 0
    1657              : 
    1658              :         // TODO FIXME das ist was komisches, was von S. Reiter da ist, es werden edges gesplittet, für was?
    1659              : 
    1660              :         edges.clear();
    1661              :         for(EdgeIterator iter = sel.begin<Edge>();
    1662              :                 iter != sel.end<Edge>(); ++iter)
    1663              :         {
    1664              :                 Edge* e = *iter;
    1665              :                 if(aaMarkVRT[e->vertex(0)] != 2 &&
    1666              :                         aaMarkVRT[e->vertex(1)] != 2 &&
    1667              :                         aaMarkEDGE[e] > 1)
    1668              :                 {
    1669              :                         edges.push_back(e);
    1670              :                 }
    1671              :         }
    1672              : 
    1673              :         for(size_t i = 0; i < edges.size(); ++i){
    1674              :                 vector3 center = CalculateCenter(edges[i], aaPos);
    1675              :                 RegularVertex* v =      SplitEdge<RegularVertex>(grid, edges[i], false);
    1676              :                 aaPos[v] = center;
    1677              :                 aaMarkVRT[v] = 2;
    1678              :                 sel.select(v);
    1679              :         //      assign adjacency values for associated selected edges (2 to each)
    1680              :                 for(Grid::AssociatedEdgeIterator iter = grid.associated_edges_begin(v);
    1681              :                         iter != grid.associated_edges_end(v); ++iter)
    1682              :                 {
    1683              :                         if(sel.is_selected(*iter))
    1684              :                                 aaMarkEDGE[*iter] = 2;
    1685              :                 }
    1686              :         }
    1687              : 
    1688              : 
    1689              : #endif
    1690              : 
    1691              :         return true;
    1692              : 
    1693              : }
    1694              : 
    1695            0 : int ArteExpandFracs3D::prepareStasi( Vertex * const & vrt, AttachedVolumeElemInfo & attVolElmInfo )
    1696              : {
    1697              :         // NOTE returns number of boundary faces
    1698              : 
    1699              :         // Voraussetzung  FÜR StammiBene Aufrufung
    1700              :         // Stammi-Bene-Vorbereitung
    1701              : //      for( VertexIterator iter = m_sel.begin<Vertex>(); iter != m_sel.end<Vertex>(); ++iter)
    1702              : //      {
    1703              : //              Vertex* vrt = *iter;
    1704              : 
    1705              : //              std::vector<Volume*> & attVol = m_aaVrtInfoAssoVols[vrt];
    1706              : 
    1707            0 :         auto & vrtxFracPrps = m_aaMarkVrtVFP[ vrt ];
    1708              : 
    1709              : //      bool isBndryVrtx = vrtxFracPrps.getIsBndFracVertex();
    1710              : 
    1711              :         IndexType numBndryFacs = 0;
    1712              : 
    1713              :                 // TODO FIXME das hier soll wegfallen, und an dieser Stelle direkt berechnet werden
    1714              :                 // damit es einheitlich für echte fracture faces und auch für boundary faces gilt,
    1715              :                 // die eine Art Fracture sind, an denen mit dem Durchmesser 0 der neue Vertex verschoben wird
    1716              : 
    1717              :                 // die erzeugen wir an Ort und Stelle neu und verteilen nicht alles auf hundert Plätze
    1718              : //              VecAttachedFractFaceEdgeSudo vecAttFacEdgSudo = vrtxFracPrps.getAllAttachedFractElems();
    1719              : 
    1720              : //              auto & vecVolElmInfo = m_aaVolElmInfo[vrt];
    1721              : 
    1722              :                 // TODO FIXME eigentlich eine Dummheit, das auf zu teilen in ein VolElemInfo und ein VrtInfoAssoVols
    1723              :                 // denn die InfoAssoVols haben als Info nur die Volumen, die VolElmInfos haben die Volumen
    1724              :                 // und noch viel mehr Infos zu den Faces und den Edges....
    1725              :                 // mittelfristig die m_aaVrtInfoAssoVols abschaffen und alles auf die AttachedFullDimElemInfo
    1726              :                 // übertragen, dann geht der folgende Loop gleich über den Vektor darüber, bzw. gleichbedeutend
    1727              :                 // über m_aaVolElmInfo
    1728              : //              for( auto & vol : attVol )
    1729              : //              for( AttachedVolumeElemInfo & attVolElmInfo : vecVolElmInfo )
    1730              : //              {
    1731              : //                      AttachedVolumeElemInfo attVolElmInfo( vol );
    1732            0 :         Volume * vol = attVolElmInfo.getFulldimElem();
    1733              : 
    1734              :                         // add those faces which are fracture faces
    1735              :                         // TODO FIXME hier müssen die fracture faces neu erzeugt und addiert werden, oder weiter unten.....
    1736              : //                      for( auto & afes : vecAttFacEdgSudo )
    1737              : //                      {
    1738              : //                              attVolElmInfo.addFractManifElem(afes, m_grid);
    1739              : //                      }
    1740              : 
    1741              :                         // add those faces which are NOT fracture faces, assign them arbitraryly subdomain  -1
    1742              :                         // to indicate that they are not from the manifold, independent of their subdomain
    1743              : 
    1744              :                         // collect all volume faces which incorporate the vertex
    1745              : 
    1746              :         std::vector<Face*> volFacesContainingVrtx;
    1747              : 
    1748            0 :         for( IndexType iFac = 0; iFac < vol->num_faces(); iFac++ )
    1749              :         {
    1750            0 :                 Face * fac = m_grid.get_face(vol,iFac);
    1751              : 
    1752            0 :                 if( FaceContains( fac, vrt ) )
    1753              :                 {
    1754            0 :                         volFacesContainingVrtx.push_back( fac );
    1755              :                 }
    1756              :         }
    1757              : 
    1758            0 :         for( auto const & fac : volFacesContainingVrtx )
    1759              :         {
    1760              :                                 // get the edges of the face connected to the vertex
    1761              : 
    1762              :                 std::vector<Edge*> vecEdgesFaceVrtx;
    1763              : 
    1764              :                                 // need to be two edges always, check
    1765              : 
    1766            0 :                 for( IndexType iEdge = 0; iEdge < fac->num_edges(); iEdge++ )
    1767              :                 {
    1768            0 :                         Edge * edg = m_grid.get_edge(fac,iEdge);
    1769              : 
    1770            0 :                         if( EdgeContains(edg,vrt) )
    1771              :                         {
    1772            0 :                                 vecEdgesFaceVrtx.push_back(edg);
    1773              :                         }
    1774              :                 }
    1775              : 
    1776            0 :                 if( vecEdgesFaceVrtx.size() != 2 )
    1777              :                 {
    1778              :                         UG_LOG("edge number Unsinn " << vecEdgesFaceVrtx.size() << std::endl);
    1779            0 :                         UG_THROW("edge number Unsinn " << vecEdgesFaceVrtx.size() << std::endl);
    1780              :                         return false;
    1781              :                 }
    1782              : 
    1783              :                 EdgePair edgesFaceVrtx( vecEdgesFaceVrtx[0], vecEdgesFaceVrtx[1] );
    1784              : 
    1785              :                                 // test the subdomain first, if from the subdomains of the cleft manifolds
    1786              : 
    1787            0 :                 IndexType sudoThisFace = m_sh.get_subset_index(fac);
    1788              : 
    1789              :                 std::vector<IndexType> const & sudoList = vrtxFracPrps.getSudoList();
    1790              : 
    1791              :                                 // test if sudo of face belongs to the fracture face subdom list
    1792              : 
    1793              :                 bool faceBelongsToFracSudo = false;
    1794              : 
    1795            0 :                 for( auto const & sudoFrac : sudoList )
    1796              :                 {
    1797            0 :                         if( sudoFrac == sudoThisFace )
    1798              :                         {
    1799              :                                 faceBelongsToFracSudo = true;
    1800              :                                 break;
    1801              :                         }
    1802              :                 }
    1803              : 
    1804              :                                 // TODO FIXME für Boundary faces und für Fracture faces soll die Normale berechnet werden ins VOlumen hinein
    1805              :                                 // hier die KuhVol-Prozedur
    1806              : 
    1807              :                 bool isBoundaryFace = false;
    1808              : 
    1809            0 :                 if( ! faceBelongsToFracSudo )
    1810              :                 {
    1811            0 :                         if( IsBoundaryFace3D( m_grid, fac ) )
    1812              :                         {
    1813              :                                 isBoundaryFace = true;
    1814              :                         }
    1815              :                 }
    1816              : 
    1817            0 :                 if( isBoundaryFace && faceBelongsToFracSudo )
    1818            0 :                         UG_THROW("not allowed to be fracture at boundary" << std::endl);
    1819              : 
    1820              :                 // will get a nonzero value in case that fracture face or boundary face
    1821              :                 NormalVectorFacIntoVol normalIntoVol(0,0,0);
    1822              : 
    1823            0 :                 if( isBoundaryFace || faceBelongsToFracSudo )
    1824              :                 {
    1825              :                                 // TODO FIXME compute normal into volume, needed to know!!!
    1826              :                                         // kuhVol Procedure
    1827            0 :                         if( ! computeNormalKuhVolProcedure(vol,fac,normalIntoVol) )
    1828              :                         {
    1829              :                                 UG_LOG("Kuh VOl schief gegangen " << std::endl);
    1830            0 :                                 UG_THROW("Kuh VOl schief gegangen " << std::endl);
    1831              :                                 return numBndryFacs;
    1832              :                         }
    1833              :                 }
    1834              : 
    1835            0 :                 if( faceBelongsToFracSudo )
    1836              :                 {
    1837              :                                         // if it belongs, construct it again and test if it already belongs to the fracture faces
    1838              :                                         // MUST be already part of the list, else major error appeared!
    1839              : 
    1840            0 :                         UG_LOG("Kuh Normale " << normalIntoVol << std::endl);
    1841              : 
    1842              :                         AttachedFractFaceEdgeSudo afesFract( fac, edgesFaceVrtx, sudoThisFace, normalIntoVol );
    1843              :                                         //  hier soll auch gleich die Normale relativ zum VOlumen dazu gespeichert werden!!
    1844              : 
    1845            0 :                         attVolElmInfo.addFractManifElem( afesFract, m_grid );
    1846              : 
    1847              :                                         // vorher soll es nicht mehr gespeichert werden, da die Infos vorher weg fallen sollen
    1848              : //                                      if( attVolElmInfo.addFractManifElem( afesFract, m_grid ) )
    1849              : //                                      {
    1850              : //                                              UG_LOG("manifold element already contained!" << std::endl);
    1851              : //                                              UG_THROW("manifold element already contained!" << std::endl);
    1852              : //                                              return false;
    1853              : //                                      }
    1854              : 
    1855              :                                         // nothing to do, already added before hoffentlich
    1856              : 
    1857              :                 }
    1858              :                 else
    1859              :                 {
    1860              :                                         // TODO FIXME hier muss entschieden werden, ob es eine boundary face ist
    1861              :                         // die kommt dann auch nochmal in ein anderes Konstrukt, was aber
    1862              :                                         // dem fracture face ähnelt
    1863              :                                         // am Ende müssen die Frac Faces, die nicht geschlossen sind, und doppelt in einem Segment
    1864              :                                         // in die general faces verschoben werden, da stören sie nicht, und sind egal
    1865              : 
    1866              :                                         // zeitweilig fehlten alle Faces, die keine fractures sind
    1867              :                                         // die müssen noch irgendwie als nicht-fracture-faces auch dazu gefügt werden
    1868              :                                         // die sind in den attached volumes schon enthalten,
    1869              :                                         // Frage: wie prüfen, dass die gar keine fractures sind, die Infos sollten bekannt sein.....
    1870              :                                         // wichtig auch, dass nur die faces dazu kommen, die den Vertex enthalten!!!
    1871              :                                         // irgendwas von der Art "nonFractureFaceInfos" oder sowas dazu hängen, mit Info
    1872              :                                         // ob schon getouched oder noch nicht.....
    1873              : 
    1874              : 
    1875              :                                         // we construct the attached manifold, given that it is NOT a fracture manifold
    1876              : 
    1877              :                                         // notwendig auch, dass es eine Markierungsmöglichkeit gibt dafür, ob
    1878              :                                         // ein face bei der nächsten weiter inneren Runde quasi äussere Begrenzung sein muss
    1879              :                                         // gilt sowohl für fracture faces, die können das in erster Runde auch sein am Ende
    1880              :                                         // der Runde, sowie danach nur noch für nicht-fracture-faces
    1881              : //                                      if( IsBoundaryFace3D( m_grid, fac ) )
    1882            0 :                         if( isBoundaryFace )
    1883              :                         {
    1884              :                                 AttachedBndryFaceEdgeSudo afesBndry( fac, edgesFaceVrtx, sudoThisFace, normalIntoVol );
    1885              : 
    1886            0 :                                 attVolElmInfo.addBndryManifElem( afesBndry, m_grid );
    1887              : 
    1888            0 :                                 UG_LOG("Boundary element added" << m_aaPos[vrt] << " -> " << normalIntoVol << std::endl);
    1889              : 
    1890            0 :                                 numBndryFacs++;
    1891              : 
    1892              : //                                                      UG_THROW("da ist es " << std::endl);
    1893              : 
    1894              :                                 // TODO FIXME sehr wichtig, die Boundary faces brauchen auch
    1895              :                                                 // noch ihre Normale in das Volumen hinein, analog zu den Fracture faces!!!
    1896              :                                                 // die haben die allerdings dummerweise in die boundary vertizes gesteckt
    1897              :                                                 // vielleicht boundaries wie fractures behandeln? keine gute Idee......
    1898              :                                                 // mithin steckt die Normale NICHT in diesen Informationen drin
    1899              :                                                 // sondern extra in den vertex fracture tripeln
    1900              :                                                 // vielleicht dort die boundaries irgendwie dazu würgen.....
    1901              : 
    1902              :                         }
    1903              :                         else // normal face, no fracture, no boundary
    1904              :                         {
    1905              :                                 AttachedGenerFaceEdgeSudo afesAdd( fac, edgesFaceVrtx );
    1906              : 
    1907            0 :                                 attVolElmInfo.addGenerManifElem( afesAdd, m_grid );
    1908              :                         }
    1909              : 
    1910              : 
    1911              :                 }
    1912              : 
    1913            0 :         }
    1914              : 
    1915              : //              }
    1916              : //      }
    1917              : 
    1918              : //      if( isBndryVrtx && numBndryFacs == 0 )
    1919              : //      {
    1920              : //              UG_LOG("boundary vertex but no boundary faces ")
    1921              : //      }
    1922              : 
    1923            0 :         return numBndryFacs;
    1924            0 : }
    1925              : 
    1926            0 : bool ArteExpandFracs3D::computeNormalKuhVolProcedure( Volume * const & kuhVol, Face * const & fac, NormalVectorFacIntoVol & normalIntoVol )
    1927              : {
    1928              :         IndexType numFd = 0;
    1929              : 
    1930            0 :         for( IndexType iSide = 0; iSide < kuhVol->num_sides(); iSide++ )
    1931              :         {
    1932            0 :                 Face * kuhFac = m_grid.get_side(kuhVol, iSide);
    1933              : 
    1934              : //                                      UG_LOG("Center Kuh Face " << CalculateCenter(kuhFac,m_aaPos) << std::endl);
    1935              : 
    1936              :                 //  eigentliches Ziel ist es, den face descriptor des Volumens zu finden,
    1937              :                 // das mit dem face übereinstimmt, alle anderen Seiten des Volumens sind egal
    1938              :                 // Funktion suchen, die ausgehend von einem Face, das ein Volumen begrenzt,
    1939              :                 // den zum Volumen passenden FaceDescriptor findet, also auch richtige Orientierung
    1940              :                 // der Vertices beinhaltet
    1941              :                 // FRAGE: ist ein face descriptor von der Orientierung zum Volumen abhängig
    1942              :                 // oder hängt der nur vom Face ab, das eine vorgegebene Oriertierung hat?
    1943              : 
    1944            0 :                 bool checkCoincide = checkIfFacesVerticesCoincide( kuhFac, fac );
    1945              : 
    1946            0 :                 if( checkCoincide )
    1947              :                 {
    1948            0 :                         numFd++;
    1949              : 
    1950            0 :                         if( kuhFac != fac )
    1951              :                                 UG_LOG("Kuh Fac ist nicht fac " << std::endl);
    1952              : 
    1953            0 :                         FaceDescriptor facDescr;
    1954              : 
    1955              :                         // testen, ob der Face Descriptor von der Orientierung abhängt
    1956              :                         // also testen, ob sich der face descriptor ändert, wenn das Volumen
    1957              :                         // auf der einen und auf der anderen Seite des faces hängt
    1958              :                         // deswegen auch die ganze Prozedur mit den kuhFacs, die hoffentlich
    1959              :                         // je nach Volumen anders orientiert sind als das eigentliche Face,
    1960              :                         // aber dieselben Vertices haben, also geometrisch gleich sind, aber anders orientiert!!!!
    1961              : 
    1962              :                         //  andere Hergehensweise vielleicht:
    1963              :                         // von m_aaVrtInfoAssoVols ausgehen, darüber loopen, oder die in einen Vektor stecken,
    1964              :                         // wo die Vertices dabei sind, dann kann man sich vielelicht ein paar Klimmzüge sparen,
    1965              :                         // vielleicht aber auch nicht.....
    1966              : 
    1967            0 :                         kuhVol->face_desc( iSide, facDescr );
    1968              : 
    1969              : //                      vector3 normal;
    1970              : 
    1971            0 :                         CalculateNormal( normalIntoVol, & facDescr, m_aaPos );
    1972              : 
    1973            0 :                         vector3 facCenter = CalculateCenter( kuhFac, m_aaPos );
    1974            0 :                         vector3 kuhCenter = CalculateCenter( fac, m_aaPos );
    1975            0 :                         vector3 kuhVolCenter = CalculateCenter( kuhVol, m_aaPos);
    1976              : 
    1977              : //                                              UG_LOG("Normale zum face descriptor " << normal << " , " << facCenter << std::endl);
    1978              : //                                              UG_LOG("Normale zum Kuhh descriptor " << normal << " , " << kuhCenter << std::endl);
    1979              : //                                              UG_LOG("Zentrum des Vol")
    1980              : 
    1981              : //                                              UG_LOG("fac " << fac << std::endl );
    1982              : //                                              UG_LOG("kuh " << kuhFac << std::endl );
    1983              : 
    1984            0 :                         UG_LOG("Normale ist " << normalIntoVol << " fac " << facCenter
    1985              :                                         << " vol " << kuhVolCenter << std::endl);
    1986              : 
    1987              : 
    1988              : //                                              VolNormPair normalsAwayVol( kuhVol, normal );
    1989              : //
    1990              : //                                              vecNormalsAwayVol.push_back( normalsAwayVol );
    1991              : 
    1992              :                 }
    1993              :         }
    1994              : 
    1995            0 :         if( numFd != 1 )
    1996              :         {
    1997            0 :                 UG_THROW("Kein Kuh Volumen gefunden" << std::endl);
    1998              :                 return false;
    1999              :         }
    2000              : 
    2001              : 
    2002              :         return true;
    2003              : }
    2004              : 
    2005              : //////////////////////////////////////////////////////////////////
    2006              : 
    2007            0 : bool ArteExpandFracs3D::distinguishSegments()
    2008              : {
    2009              : 
    2010              :         UG_LOG("neuer Beginn Segmente" << std::endl);
    2011              : //      return true;
    2012              : 
    2013              :         //      StammiBene Algorithmus erklärt und in Worten Plan erstellt
    2014              :         //      Search the adjacent merged manifold iteratively between each necessary element
    2015              :         // TODO FIXME hier Loop über alle selektierten Vertizes
    2016              :         // darin für jeden Vertex die adjungierten Volumen bestimmen ohne Vorbedingung
    2017              :         // dann den Loop zur Vorbereitung des StammiBene Algorithmus aufrufen
    2018              :         // für jeden Vertex wieder, der hat dann schon die Basisinfo von der
    2019              :         // VecAttachedVolumeElemInfo Klasse an jedem Vertex
    2020              :         // auf die aufbauend fügt er Fracture  Manifolds, general manifolds,
    2021              :         // und NEU auch boundary manifolds in einer eigenen Member dazu
    2022              :         // danach wird für jeden Vertex der StammiBene Algorithmus aufgerufen
    2023              :         // später werden Boundary Faces wie eine eigene Subdomain Ebene
    2024              :         // mit Expansion null behandelt
    2025              :         // was an Knicken aussen an boundary zu tun ist, noch zu überlegen
    2026              : 
    2027              :         UG_LOG("Stasi Algo alle Vrt Start << std::endl");
    2028              : 
    2029            0 :         for( VertexIterator iter = m_sel.begin<Vertex>(); iter != m_sel.end<Vertex>(); ++iter)
    2030              :         {
    2031            0 :                 Vertex* vrt = *iter;
    2032              : 
    2033            0 :                 if( ! stasiAlgo( vrt ) )
    2034              :                 {
    2035              :                         UG_LOG("Stasi schief gegangen " << std::endl);
    2036            0 :                         UG_THROW("Stasi schief gegangen" << std::endl);
    2037              :                         return false;
    2038              :                 }
    2039              :         }
    2040              : 
    2041              :         UG_LOG("Stasi Algo alle Vrt End << std::endl");
    2042              : 
    2043              :         // TODO FIXME
    2044              :         // es müssen in den Segmenten noch die fracture faces zu generellen faces verschoben werden,
    2045              :         // die nicht abgeschlossen sind, und umgangen werden können, und so in die Landschaft ragen
    2046              :         // also die fracture faces, die für die Segmenteigenschaft unerheblich sind
    2047              : 
    2048            0 :         for( VertexIterator iter = m_sel.begin<Vertex>(); iter != m_sel.end<Vertex>(); ++iter)
    2049              :         {
    2050            0 :                 Vertex* vrt = *iter;
    2051              : 
    2052            0 :                 IndexType shiFraFac = shiftUnclosedFracFacesToUnclosedFractFaces( vrt );
    2053              : 
    2054            0 :                 UG_LOG("shifted frac faces at " << m_aaPos[vrt] << shiFraFac << std::endl);
    2055              :         }
    2056              : 
    2057              : 
    2058              :         return true;
    2059              : 
    2060              : }
    2061              : 
    2062              : //////////////////////////////////////////////////////////////////
    2063              : 
    2064              : 
    2065            0 : bool ArteExpandFracs3D::detectEndingCrossingCleftsSegmBased()
    2066              : {
    2067              : 
    2068            0 :         m_vecEdgeDirectConnectingEndingCrossCleftVrtcs = std::vector<Edge*>();
    2069              : 
    2070              :         // TODO FIXME eigene Klasse erzeugen, die die ganzen Infos an endenden Klüften speichert, wo sich
    2071              :         // zwei Klüfte kreuzen
    2072              :         // Vertex, auslaufende faces, wo anders aufgeblasen werden muss,
    2073              :         // Edges der Kreuzung, die anhängenden faces der anderen Kluft, die
    2074              :         // die Basis sind für die Aufblasungen, die auch anders funktionieren
    2075              :         // von dieser Klasse dann ein attachment an die vertizes und vielleicht die faces,
    2076              :         // die problematisch sind
    2077              :         // (noch zu klären, ob vielleicht ein paar der auskommentierten attachments doch sinnvoll)
    2078              : 
    2079              :         IndexType numEndingCrossingClefts = 0;
    2080              : 
    2081              : //      std::vector<Face*> m_d_endingCrossingCleftFaces;
    2082              : //
    2083              : //      std::vector<Vertex*> m_d_endingCrossingCleftVrtcs;
    2084              : //
    2085              : //      std::vector<Edge*> m_d_cuttingEdges;
    2086              : //      std::vector<Face*> crossingNotEndingFaces;
    2087              : //
    2088              : //      std::vector<Edge*> otherEdgeOfCrossingNotEndingFace;
    2089              : //      std::vector<Face*> nextFaceOfCrossingNotEndingFaces;
    2090              : 
    2091            0 :         for( VertexIterator iter = m_sel.begin<Vertex>(); iter != m_sel.end<Vertex>(); ++iter)
    2092              :         {
    2093            0 :                 Vertex* vrt = *iter;
    2094              : 
    2095              :                 VecSegmentLimitingSides & vecSegmLimSid = m_vrtxAttAccsVecSegmLimSid[vrt];
    2096              : 
    2097            0 :                 if(  vecSegmLimSid.size() == 0 )
    2098              :                 {
    2099              :                         UG_LOG("keine verschiedenen Segmente ECCV" << std::endl);
    2100              : //                      return true;
    2101              :                 }
    2102              : 
    2103            0 :                 if( vecSegmLimSid.size() == 1 )
    2104              :                 {
    2105              :                         UG_LOG("sonderbarer Fall von nur einem Segment ECCV" << std::endl );
    2106            0 :                         UG_THROW("sonderbarer Fall von nur einem Segment ECCV" << std::endl );
    2107            0 :                         return false;
    2108              :                 }
    2109              : 
    2110            0 :                 for( SegmentLimitingSides & segLimSids : vecSegmLimSid )
    2111              :                 {
    2112            0 :                         if( segLimSids.hasUnclosedFaces() )
    2113              :                         {
    2114              :                                 UG_LOG("im distinguisch ungeschlossene Gesichter " << std::endl );
    2115              : 
    2116            0 :                                 numEndingCrossingClefts++;
    2117              : 
    2118              :                                 std::vector<Volume*> volsOfUnclosedSegm;
    2119              : 
    2120            0 :                                 if( ! segLimSids.spuckVecFulldimElem(volsOfUnclosedSegm) )
    2121              :                                 {
    2122              :                                         UG_LOG("No volumes at segment with ending cleft" << std::endl);
    2123            0 :                                         UG_THROW("No volumes at segment with ending cleft" << std::endl);
    2124              :                                         return false;
    2125              :                                 }
    2126              : 
    2127            0 :                                 for( Volume * vol : volsOfUnclosedSegm )
    2128              :                                 {
    2129              :                                         m_volAttAccsVolTouchesEndingCrossingCleft[vol] = true;
    2130              :                                 }
    2131              : 
    2132              :                                 Vertex * endingCrossingCleftVrtx = segLimSids.spuckVertex();
    2133              : 
    2134            0 :                                 if( endingCrossingCleftVrtx != vrt )
    2135              :                                 {
    2136            0 :                                         UG_THROW("System von attachments und vektoren durcheinander " << std::endl);
    2137              :                                 }
    2138              : 
    2139              :                                 //  commented out the debug members:  m_d_endingCrossingCleftVrtcs.push_back( endingCrossingCleftVrtx );
    2140              : 
    2141              :                                 UG_LOG("vertex gefunden an ending crossing cleft " << std::endl);
    2142              : 
    2143              :                                 m_aaMarkVrtxAtEndingCrossingCleft[vrt] = true;
    2144              : 
    2145              :                                 // the unclosed ending crossing faces
    2146              :                                 VecSegLimSidesFractFace vecSegmLimSiFFUnclosed;
    2147              : 
    2148              :                                 if( ! segLimSids.spuckVecAttUnclosedFractElm( vecSegmLimSiFFUnclosed ) )
    2149              :                                         return false;
    2150              : 
    2151              :                                 // figure out the faces that are in touch with the ending faces, and the corresponding edges
    2152              : 
    2153              :                                 VecSegLimSidesFractFace vecSegmLimSiFFClosed;
    2154              : 
    2155              :                                 if( ! segLimSids.spuckVecAttFractElm( vecSegmLimSiFFClosed ) )
    2156              :                                         return false;
    2157              : 
    2158              :                                 UG_LOG("Faces suchen an ending crossing cleft " << std::endl);
    2159              : 
    2160              : //                              Face * endingFractManifCutting = nullptr;
    2161              : //                              Face * endingFractManifNotCutting = nullptr;
    2162              : //                              Edge * oldLowDimElCut = nullptr;
    2163              : //                              std::pair<Face*,Face*> pairNeighbouredFractClosedManifEl(nullptr,nullptr);
    2164              : //                              IndexType sudoFractEnding = std::numeric_limits<IndexType>::max();
    2165              : //                              IndexType sudoFractNotEnding = std::numeric_limits<IndexType>::max();
    2166              : 
    2167              :                                 std::vector<Face*> vecEndingFractFaceCutting; // must have size two after been filled but both same content
    2168              :                                 std::vector<Face*> vecEndingFractFaceNotCutting; // can contain an arbitrary number from zero to .....
    2169              :                                 std::vector<Face*> vecNeighbouredFacesClosedFract; // must have size 2
    2170              : 
    2171              :                                 std::vector<IndexType> vecSudoFractFacsEnding; // must be filled with same number
    2172              :                                 std::vector<IndexType> vecSudoFractFacsNotEnding; // must be filled with same number
    2173              : 
    2174              :                                 std::vector<Edge*> vecCuttingEdges; // must contain only same element, twice
    2175              : 
    2176              :                                 std::vector<Edge*> vecUncuttingEdge; // must get same element twice
    2177              : 
    2178              :                                 UG_LOG("size of vec segm unclos " << vecSegmLimSiFFUnclosed.size() << std::endl);
    2179              : 
    2180            0 :                                 for( SegLimSidesFractFace const & slsffUncl : vecSegmLimSiFFUnclosed )
    2181              :                                 {
    2182              :                                         bool isCuttingTheClosed = false;
    2183              : 
    2184            0 :                                         Face * facUncl = slsffUncl.getManifElm();
    2185              :                                         //  commented out the debug members:  m_d_endingCrossingCleftFaces.push_back(facUncl);
    2186              :                                         m_aaMarkFaceWithEndingCrossingCleft[facUncl] = true;
    2187              : 
    2188            0 :                                         IndexType sudoUncl = slsffUncl.getSudo();
    2189            0 :                                         vecSudoFractFacsEnding.push_back(sudoUncl);
    2190              : 
    2191              :                                         EdgePair const & epU = slsffUncl.getPairLowElm();
    2192              : 
    2193              :                                         //  commented out the debug members:  m_d_allContributingEdges.push_back(epU.first);
    2194              :                                         //  commented out the debug members:  m_d_allContributingEdges.push_back(epU.second);
    2195              : 
    2196              :                                         addElem( m_vecEdgeDirectConnectingEndingCrossCleftVrtcs, epU.first );
    2197              :                                         addElem( m_vecEdgeDirectConnectingEndingCrossCleftVrtcs, epU.second );
    2198              : 
    2199            0 :                                         for( SegLimSidesFractFace const & slsffClos : vecSegmLimSiFFClosed )
    2200              :                                         {
    2201              :                                                 // we need different subdoms, as want to have the not ending crossing fracture neighbours
    2202              :                                                 // that have a common edge
    2203            0 :                                                 Edge * commonEdge = nullptr;
    2204              : 
    2205            0 :                                                 if( fractFacesAreNeighboured<false>( slsffClos, slsffUncl, commonEdge ) )
    2206              :                                                 {
    2207              :                                                         isCuttingTheClosed = true;
    2208              : 
    2209            0 :                                                         Face * facClos = slsffClos.getManifElm();
    2210              :                                                         //  commented out the debug members:  m_d_crossingNeighboredNotEndingFaces.push_back( facClos );
    2211              : 
    2212            0 :                                                         if( commonEdge == nullptr )
    2213              :                                                         {
    2214              :                                                                 UG_LOG("NULL COMMON" << std::endl);
    2215            0 :                                                                 UG_THROW("NULL COMMON" << std::endl);
    2216              :                                                         }
    2217              : 
    2218              :                                                         //  commented out the debug members:  m_d_cuttingEdges.push_back(commonEdge);
    2219              :                                                         //  commented out the debug members:  m_d_crossingNeighboredNotEndingFacesCommEdg.push_back(facUncl);
    2220              : //                                                      // search the durchgehende fracture face which is neighboured to the durchgehende one
    2221              : //                                                      // same vertex, other edge
    2222              : 
    2223            0 :                                                         vecNeighbouredFacesClosedFract.push_back(facClos);
    2224            0 :                                                         vecCuttingEdges.push_back(commonEdge);
    2225            0 :                                                         vecEndingFractFaceCutting.push_back(facUncl);
    2226              : 
    2227            0 :                                                         Edge * uncuttingEdgeUnclosedFac = nullptr;
    2228              : 
    2229            0 :                                                         if( ! assignNotCuttingEdgeUnclosedCrossingCleft( slsffUncl, commonEdge, uncuttingEdgeUnclosedFac ) )
    2230              :                                                         {
    2231              :                                                                 UG_LOG("NO shift edge" << std::endl);
    2232            0 :                                                                 UG_THROW("NO shift edge" << std::endl);
    2233              :                                                         }
    2234              : 
    2235            0 :                                                         if( uncuttingEdgeUnclosedFac == nullptr )
    2236              :                                                         {
    2237              :                                                                 UG_LOG("NO shift edge Z" << std::endl);
    2238            0 :                                                                 UG_THROW("NO shift edge Z" << std::endl);
    2239              :                                                         }
    2240              : 
    2241            0 :                                                         vecUncuttingEdge.push_back(uncuttingEdgeUnclosedFac);
    2242              : 
    2243              :                                                         //                                                      EdgePair const & edgesClosedFracFace = slsffClos.getPairLowElm();
    2244              : //
    2245              : //                                                      Edge * notCommonEdgeOfNotEndingCleft = nullptr;
    2246              : //
    2247              : //                                                      if(  edgesClosedFracFace.first == commonEdge )
    2248              : //                                                      {
    2249              : //                                                              notCommonEdgeOfNotEndingCleft = edgesClosedFracFace.second;
    2250              : //                                                      }
    2251              : //                                                      else if( edgesClosedFracFace.second == commonEdge )
    2252              : //                                                      {
    2253              : //                                                              notCommonEdgeOfNotEndingCleft = edgesClosedFracFace.first;
    2254              : //                                                      }
    2255              : //
    2256              : //                                                      if( notCommonEdgeOfNotEndingCleft == nullptr )
    2257              : //                                                      {
    2258              : //                                                              UG_LOG("no not common edge?" << std::endl);
    2259              : //                                                              UG_THROW("no not common edge?" << std::endl);
    2260              : //                                                      }
    2261              : //
    2262              : ////                                                    otherEdgeOfCrossingNotEndingFace.push_back( notCommonEdgeOfNotEndingCleft );
    2263              : //
    2264              : //                                                      Edge * closedCommonEdge = nullptr;
    2265              : //
    2266              : //                                                      for( SegLimSidesFractFace const & slsffClosOther : vecSegmLimSiFFClosed )
    2267              : //                                                      {
    2268              : //                                                              if( fractFacesAreNeighboured<true>( slsffClos, slsffClosOther, closedCommonEdge ) )
    2269              : //                                                              {
    2270              : //
    2271              : //                                                                      if( closedCommonEdge == nullptr )
    2272              : //                                                                      {
    2273              : //                                                                              UG_LOG("NULL NOT COMMON" << std::endl);
    2274              : //                                                                              UG_THROW("NULL NOT COMMON" << std::endl);
    2275              : //                                                                      }
    2276              : //
    2277              : //                                                                      if( closedCommonEdge != notCommonEdgeOfNotEndingCleft )
    2278              : //                                                                      {
    2279              : //                                                                              UG_LOG("Ecke passt nicht " << CalculateCenter(closedCommonEdge, m_aaPos) << " - " << CalculateCenter( notCommonEdgeOfNotEndingCleft, m_aaPos) << std::endl);
    2280              : ////                                                                            UG_THROW("Ecke verloren " << std::endl);
    2281              : //                                                                      }
    2282              : //                                                                      else
    2283              : //                                                                      {
    2284              : //                                                                              Face * facClosOther = slsffClosOther.getManifElm();
    2285              : //
    2286              : //                                                                              nextFaceOfCrossingNotEndingFaces.push_back( facClosOther );
    2287              : //                                                                              otherEdgeOfCrossingNotEndingFace.push_back(notCommonEdgeOfNotEndingCleft);
    2288              : //                                                                      }
    2289              : //
    2290              : //
    2291              : //                                                              }
    2292              : //                                                      }
    2293              : 
    2294              : 
    2295              :                                                 }
    2296              :                                         }
    2297              : 
    2298            0 :                                         if( ! isCuttingTheClosed )
    2299              :                                         {
    2300            0 :                                                 vecEndingFractFaceNotCutting.push_back(facUncl);
    2301              :                                         }
    2302              : 
    2303              :                                 }
    2304              : 
    2305              : 
    2306              :                                 std::vector<Face*> vecClosedFracFacNoNeighbr;
    2307              : 
    2308            0 :                                 for( SegLimSidesFractFace const & slsffClos : vecSegmLimSiFFClosed )
    2309              :                                 {
    2310            0 :                                         Face * facClos = slsffClos.getManifElm();
    2311              : 
    2312              :                                         EdgePair const & epC = slsffClos.getPairLowElm();
    2313              : 
    2314              :                                         //  commented out the debug members:  m_d_allContributingEdges.push_back(epC.first);
    2315              :                                         //  commented out the debug members:  m_d_allContributingEdges.push_back(epC.second);
    2316              : 
    2317              :                                         addElem( m_vecEdgeDirectConnectingEndingCrossCleftVrtcs, epC.first );
    2318              :                                         addElem( m_vecEdgeDirectConnectingEndingCrossCleftVrtcs, epC.second );
    2319              : 
    2320              : 
    2321            0 :                                         IndexType sudoClos = slsffClos.getSudo();
    2322              : 
    2323            0 :                                         vecSudoFractFacsNotEnding.push_back(sudoClos);
    2324              : 
    2325              :                                         // valid for all closed faces
    2326              :                                         m_facAttAccsIfFaceIsSegmLimFaceEndingCrossingCleft[facClos] = true;
    2327              : 
    2328              :                                         bool facGiven = false;
    2329              : 
    2330              :                                         // ATTENTION hier ausgetauscht erst später, Gefahr von Fehler
    2331              :                                         // m_d_ Variable war Teil von echtem Algorithmus, gefährlich
    2332              :                                         // hoffentlich richtig getauscht
    2333              :                                         // im Falle von bugs hier nochmal testen, ob die m_d Variable
    2334              :                                         // richtig getauscht wurde!!!
    2335              : //                                      for( Face * facClosNoNei : m_d_crossingNeighboredNotEndingFaces )
    2336            0 :                                         for( Face * facClosNoNei : vecNeighbouredFacesClosedFract )
    2337              :                                         {
    2338            0 :                                                 if( facClosNoNei == facClos )
    2339              :                                                 {
    2340              :                                                         facGiven = true;
    2341              :                                                         break;
    2342              :                                                 }
    2343              :                                         }
    2344              : 
    2345            0 :                                         if( ! facGiven )
    2346              :                                         {
    2347              :                                                 //  commented out the debug members:  m_d_notEndingCrossingFacesNotNeighbour.push_back( facClos );
    2348            0 :                                                 vecClosedFracFacNoNeighbr.push_back( facClos );
    2349              :                                         }
    2350              :                                 }
    2351              : 
    2352              : 
    2353              :                                 UG_LOG("Faces vielleicht gefunden an ending crossing cleft " << std::endl);
    2354              : 
    2355              :                                 //                              Face * endingFractManifCutting = nullptr;
    2356              :                                 //                              Face * endingFractManifNotCutting = nullptr;
    2357              :                                 //                              Edge * oldLowDimElCut = nullptr;
    2358              :                                 //                              std::pair<Face*,Face*> pairNeighbouredFractClosedManifEl(nullptr,nullptr);
    2359              :                                 //                              IndexType sudoFractEnding = std::numeric_limits<IndexType>::max();
    2360              :                                 //                              IndexType sudoFractNotEnding = std::numeric_limits<IndexType>::max();
    2361              : 
    2362              :                                 std::vector<Face*> vecContEndingFractFaceCutting; // must have size two after been filled but both same content
    2363              :                                 std::vector<Face*> vecContEndingFractFaceNotCutting; // must have size maximum two same content both, or zero
    2364              :                                 std::vector<Face*> vecContNeighbouredFacesClosedFract; // must have size 2
    2365              : 
    2366              : 
    2367              :                                 std::vector<IndexType> vecContSudoFractFacsEnding; // must be filled with same number
    2368              :                                 std::vector<IndexType> vecContSudoFractFacsNotEnding; // must be filled with same number
    2369              : 
    2370            0 :                                 if( vecEndingFractFaceCutting.size() == 2 )
    2371              :                                 {
    2372            0 :                                         if( ! checkIfContentUnique( vecEndingFractFaceCutting, vecContEndingFractFaceCutting, 1 ) )
    2373              :                                         {
    2374            0 :                                                 for( Face * fac : vecEndingFractFaceCutting  )
    2375              :                                                 {
    2376            0 :                                                         m_sh.assign_subset( fac, m_sh.num_subsets());
    2377              : 
    2378            0 :                                                         UG_LOG("fract face cutting strange behaviour at " << CalculateCenter( fac, m_aaPos ) << std::endl);
    2379              :                                                 }
    2380              : 
    2381              :                                                 UG_LOG("Problem with cutting fac " << std::endl);
    2382              :                                                 return false;
    2383              :                                                 UG_THROW("Problem with cutting fac " << std::endl);
    2384              :                                         }
    2385              :                                 }
    2386              :                                 else
    2387              :                                 {
    2388            0 :                                         UG_THROW("Problem with cutting fac size " << std::endl);
    2389              : 
    2390              :                                 }
    2391              : 
    2392            0 :                                 Face * endingFractManifCutting = vecContEndingFractFaceCutting[0];
    2393              : //
    2394              : //                              std::vector<Face> endingFractManifNotCutting; // = nullptr;
    2395              : //
    2396              : //                              if( vecEndingFractFaceNotCutting.size() != 0 )
    2397              : //                              {
    2398              : //                                      if( vecEndingFractFaceNotCutting.size() == 1 )
    2399              : //                                      {
    2400              : //                                              if( ! checkIfContentUnique( vecEndingFractFaceNotCutting, vecContEndingFractFaceNotCutting, 1 ) )
    2401              : //                                              {
    2402              : //                                                      UG_THROW("Problem with not cutting fac " << std::endl);
    2403              : //                                              }
    2404              : //
    2405              : //                                              endingFractManifNotCutting = vecContEndingFractFaceNotCutting[0];
    2406              : //
    2407              : //                                      }
    2408              : //                                      else
    2409              : //                                      {
    2410              : //                                              for( Face * fac : vecEndingFractFaceNotCutting )
    2411              : //                                              {
    2412              : //                                                      m_sh.assign_subset( fac, m_sh.num_subsets() );
    2413              : //                                              }
    2414              : //
    2415              : //                                              UG_LOG("schief gegangen " << std::endl);
    2416              : //                                              UG_LOG("Problem with not cutting fac size " << vecEndingFractFaceNotCutting.size() << std::endl);
    2417              : //
    2418              : //                                              return false;
    2419              : //                                              UG_THROW("Problem with not cutting fac size " << vecEndingFractFaceNotCutting.size() << std::endl);
    2420              : //
    2421              : //                                      }
    2422              : //
    2423              : //                              }
    2424              : 
    2425              : 
    2426            0 :                                 if( vecNeighbouredFacesClosedFract.size() == 2  )
    2427              :                                 {
    2428            0 :                                         if( ! checkIfContentUnique( vecNeighbouredFacesClosedFract, vecContNeighbouredFacesClosedFract, 2 ) )
    2429              :                                         {
    2430            0 :                                                 UG_THROW("Problem with neigh clos fac " << std::endl);
    2431              :                                         }
    2432              : 
    2433              :                                 }
    2434              :                                 else
    2435              :                                 {
    2436            0 :                                         UG_THROW("Problem with neigh clos fac size " << std::endl);
    2437              :                                 }
    2438              : 
    2439              :                                 std::pair<Face*,Face*> pairNeighbouredFractClosedManifEl( vecContNeighbouredFacesClosedFract[0],
    2440              :                                                                                                                                                   vecContNeighbouredFacesClosedFract[1]
    2441              :                                                                                                                                                  );
    2442              : 
    2443              : 
    2444            0 :                                 if(  ! checkIfContentUnique( vecSudoFractFacsEnding, vecContSudoFractFacsEnding, 1 ) )
    2445              :                                 {
    2446            0 :                                         UG_THROW("Problem with sudo ending " << std::endl);
    2447              :                                 }
    2448              : 
    2449            0 :                                 IndexType sudoFractEnding = vecContSudoFractFacsEnding[0];
    2450              : 
    2451            0 :                                 if(  ! checkIfContentUnique( vecSudoFractFacsNotEnding, vecContSudoFractFacsNotEnding, 1 ) )
    2452              :                                 {
    2453            0 :                                         UG_THROW("Problem with sudo not ending " << std::endl);
    2454              :                                 }
    2455              : 
    2456              : 
    2457            0 :                                 IndexType sudoFractNotEnding = vecContSudoFractFacsNotEnding[0];
    2458              : 
    2459              :                                 std::vector<Edge*> vecContCuttingEdges; // must contain only same element, twice
    2460              : 
    2461            0 :                                 if( vecCuttingEdges.size() == 2 )
    2462              :                                 {
    2463            0 :                                         if(  ! checkIfContentUnique( vecCuttingEdges, vecContCuttingEdges, 1 ) )
    2464              :                                         {
    2465            0 :                                                 UG_THROW("Problem with edges unique " << std::endl);
    2466              :                                         }
    2467              : 
    2468              :                                 }
    2469              :                                 else
    2470              :                                 {
    2471            0 :                                         UG_THROW("Problem with edges unique size " << std::endl);
    2472              : 
    2473              :                                 }
    2474              : 
    2475            0 :                                 Edge * oldLowDimElCut = vecContCuttingEdges[0];
    2476              : 
    2477              :                                 UG_LOG("Pushing back Edge" << std::endl);
    2478              : 
    2479              :                                 std::vector<Edge*> vecContUncuttingEdge; // must get same elemes twice
    2480              : 
    2481            0 :                                 if( vecUncuttingEdge.size() == 2 )
    2482              :                                 {
    2483            0 :                                         if(  ! checkIfContentUnique( vecUncuttingEdge, vecContUncuttingEdge, 1 ) )
    2484              :                                         {
    2485            0 :                                                 UG_THROW("Problem with edges shift unique " << std::endl);
    2486              :                                         }
    2487              : 
    2488              :                                 }
    2489              :                                 else
    2490              :                                 {
    2491            0 :                                         UG_THROW("Problem with edges shift unique size " << std::endl);
    2492              : 
    2493              :                                 }
    2494              : 
    2495            0 :                                 Edge * uncuttingLowDimEl = vecContUncuttingEdge[0];
    2496              : 
    2497            0 :                                 Edge * shiftLowDimEl = nullptr;
    2498              : 
    2499              :                                 std::vector<Edge*> vecEdgsNotCutFaces;
    2500              : 
    2501            0 :                                 if( ! findShiftEdgeUncuttingCrossingCleft( vecSegmLimSiFFUnclosed,
    2502              : //                                                                                                                 endingFractManifCutting,
    2503              :                                                                                                                vecEndingFractFaceNotCutting,
    2504              :                                                                                                                    uncuttingLowDimEl,
    2505              :                                                                                                                    shiftLowDimEl,
    2506              :                                                                                                                    vecEdgsNotCutFaces
    2507              :                                                                                                                   )
    2508              :                                         )
    2509              :                                 {
    2510              :                                         UG_LOG("Kein shift Element gefunden" << std::endl);
    2511            0 :                                         UG_THROW("Kein shift Element gefunden" << std::endl);
    2512              :                                 }
    2513              : 
    2514            0 :                                 if( shiftLowDimEl == nullptr )
    2515              :                                 {
    2516              :                                         UG_LOG("SHift El null " << std::endl);
    2517            0 :                                         UG_THROW("SHift El null " << std::endl);
    2518              :                                 }
    2519              : 
    2520            0 :                                 if(  vecClosedFracFacNoNeighbr.size() + vecNeighbouredFacesClosedFract.size()
    2521              :                                         !=  vecSegmLimSiFFClosed.size()
    2522              :                                 )
    2523              :                                 {
    2524            0 :                                         UG_THROW("size sum clos not fit " << std::endl);
    2525              :                                 }
    2526              : 
    2527              :                                 EndingCrossingFractureSegmentInfo ecfsi( vrt,
    2528              :                                                                                                              endingFractManifCutting,
    2529              :                                                                                                              vecEndingFractFaceNotCutting,
    2530              :                                                                                                                  oldLowDimElCut,
    2531              :                                                                                                                  pairNeighbouredFractClosedManifEl,
    2532              :                                                                                                                  shiftLowDimEl,
    2533              :                                                                                                                  vecEdgsNotCutFaces,
    2534              :                                                                                                                  sudoFractEnding,
    2535              :                                                                                                                  sudoFractNotEnding
    2536            0 :                                                                                                             );
    2537              : 
    2538              :                                 ecfsi.schluckVecClosedFracManifElNoNeighbr( vecClosedFracFacNoNeighbr );
    2539              : 
    2540              :                                 ecfsi.schluckVecFulldimElm( volsOfUnclosedSegm );
    2541              : 
    2542            0 :                                 m_vrtxAttAccsVecEndingCrossFractSegmInfo[vrt].push_back( ecfsi );
    2543              : 
    2544            0 :                                 m_vecEndCrossFractSegmInfo.push_back( ecfsi );
    2545              : 
    2546              : 
    2547            0 :                                 segLimSids.schluckLowdimElmShiftDirectionIfUnclosedFractPresent(shiftLowDimEl);
    2548              : 
    2549              :                                 // schlechte Idee: die segment limiting sides müssen die ganze EndingCrossingFractureSegmentInfo zu wissen bekommen
    2550              :                                 // klar alternativ sollte die shift direction reichen, um die ending crossing fracture segment info rekonstruieren zu können
    2551              :                                 // wäre aber ein Umweg!!!
    2552              :                                 // besser aber der Umweg, ansonsten entsteht das Henne Ei Problem:
    2553              :                                 // wer ist von was der Ursprung? wer schluckt was,
    2554              :                                 // die Segment Seite die Ending crossing fracture segment info, oder umgekehrt?
    2555              :                                 // und wenn es dann als Kopie geschluckt wird, was passiert wenn was verändert wird,
    2556              :                                 // es müssten also Pointer sein, und es entsteht eine unsinnige Kaskade.....
    2557              : 
    2558            0 :                         }
    2559              :                 }
    2560              : 
    2561              :         }
    2562              : 
    2563              :         UG_LOG("detected ending crossing cleft faces " << numEndingCrossingClefts << std::endl);
    2564              : 
    2565              :         UG_LOG("EDGES number " << m_vecEdgeDirectConnectingEndingCrossCleftVrtcs.size() << std::endl);
    2566              : 
    2567              : //      if( m_d_endingCrossingCleftVrtcs.size() == 0 )
    2568              : //              return true;
    2569              : 
    2570            0 :         if( splitEdgesOfNeighboredEndingCrossingFracVrtcs() )
    2571              :         {
    2572              :                 UG_LOG("needed to split, please restart with this geometry" << std::endl);
    2573            0 :                 m_needToSplitEdgesConnectingNeighbrdEndingCrossCleftVrtx = true;
    2574            0 :                 return false;
    2575              :         }
    2576              :         else
    2577              :         {
    2578            0 :                 m_needToSplitEdgesConnectingNeighbrdEndingCrossCleftVrtx = false;
    2579              :         }
    2580              : 
    2581              : //      return true;
    2582              : 
    2583              : 
    2584            0 :         for( VertexIterator iter = m_sel.begin<Vertex>(); iter != m_sel.end<Vertex>(); ++iter)
    2585              :         {
    2586              :                 Vertex* vrt = *iter;
    2587              : 
    2588              :                 VecSegmentLimitingSides & vecSegmLimSid = m_vrtxAttAccsVecSegmLimSid[vrt];
    2589              : 
    2590            0 :                 for( SegmentLimitingSides const & sls : vecSegmLimSid )
    2591              :                 {
    2592            0 :                         if( sls.hasUnclosedFaces())
    2593              :                                 UG_LOG("Hier nach detect hat das Gesicht noch ungeschlossene " << std::endl);
    2594              :                 }
    2595              : 
    2596              :         }
    2597              : 
    2598              :         if( numEndingCrossingClefts == 0 )
    2599              :                         return true;
    2600              : 
    2601              : //      assignDebugSubsets( true );
    2602              : //
    2603              : //      UG_LOG("problematic elements highlighted " << std::endl);
    2604              : 
    2605              :         return true;
    2606              : 
    2607              : 
    2608              : 
    2609              : //      if( numEndingCrossingClefts == 0 )
    2610              : //              return true;
    2611              : //
    2612              : //      // debug for ending crossing clefts
    2613              : //
    2614              : //      for( Face * fac : m_d_endingCrossingCleftFaces )
    2615              : //      {
    2616              : //              m_sh.assign_subset( fac, m_sh.num_subsets());
    2617              : //
    2618              : //      }
    2619              : //
    2620              : //      for( Vertex * vrt : m_d_endingCrossingCleftVrtcs )
    2621              : //      {
    2622              : //              m_sh.assign_subset( vrt, m_sh.num_subsets());
    2623              : //      }
    2624              : //
    2625              : //      for( Edge * edg : m_d_cuttingEdges )
    2626              : //      {
    2627              : //              if( edg == nullptr )
    2628              : //              {
    2629              : //                      UG_LOG("NULL UNERLAUBT" << std::endl);
    2630              : //                      UG_THROW("NULL UNERLAUBT" << std::endl);
    2631              : //              }
    2632              : //
    2633              : //              m_sh.assign_subset( edg, m_sh.num_subsets());
    2634              : //
    2635              : //      }
    2636              : //
    2637              : //      for( Face * fac : crossingNotEndingFaces )
    2638              : //      {
    2639              : //              m_sh.assign_subset( fac, m_sh.num_subsets());
    2640              : //      }
    2641              : //
    2642              : //      for( Edge * edg : otherEdgeOfCrossingNotEndingFace )
    2643              : //      {
    2644              : //              if( edg == nullptr )
    2645              : //              {
    2646              : //                      UG_LOG("NULL C UNERLAUBT" << std::endl);
    2647              : //                      UG_THROW("NULL C UNERLAUBT" << std::endl);
    2648              : //              }
    2649              : //
    2650              : //              m_sh.assign_subset( edg, m_sh.num_subsets());
    2651              : //
    2652              : //      }
    2653              : //
    2654              : //      for( Face * fac : nextFaceOfCrossingNotEndingFaces )
    2655              : //      {
    2656              : //              m_sh.assign_subset( fac, m_sh.num_subsets());
    2657              : //      }
    2658              : //
    2659              : //
    2660              : //      return false;
    2661              : }
    2662              : 
    2663              : //////////////////////////////////////////////////////////////////
    2664              : 
    2665            0 : bool ArteExpandFracs3D::assignNotCuttingEdgeUnclosedCrossingCleft( SegLimSidesFractFace const & slsffUncl, Edge * const & commonEdge, Edge * & shiftEdge )
    2666              : {
    2667              :         EdgePair const & edgesFac = slsffUncl.getPairLowElm();
    2668              : 
    2669              :         Edge * edgeFrst = edgesFac.first;
    2670              :         Edge * edgeScnd = edgesFac.second;
    2671              : 
    2672            0 :         if( edgeFrst == commonEdge )
    2673              :         {
    2674            0 :                 shiftEdge = edgeScnd;
    2675              :         }
    2676            0 :         else if( edgeScnd == commonEdge )
    2677              :         {
    2678            0 :                 shiftEdge = edgeFrst;
    2679              :         }
    2680              :         else
    2681              :         {
    2682              :                 UG_LOG("common and shift edge different face " << std::endl);
    2683            0 :                 UG_THROW("common and shift edge different face " << std::endl);
    2684              :         }
    2685              : 
    2686            0 :         if( shiftEdge != nullptr )
    2687              :                 return true;
    2688              : 
    2689              :         UG_LOG("shift edge null" << std::endl);
    2690              : 
    2691              :         return false;
    2692              : 
    2693              : }
    2694              : 
    2695              : //////////////////////////////////////////////////////////////////
    2696              : 
    2697            0 : bool ArteExpandFracs3D::findShiftEdgeUncuttingCrossingCleft( VecSegLimSidesFractFace const & vecSegmLimSiFFUnclosed,
    2698              : //                                                                                                                       Face * const & endingFractManifCutting,
    2699              :                                                                                                                      std::vector<Face*> const & vecEndingFractManifNotCutting,
    2700              :                                                                                                                          Edge * const & uncuttingLowDimEl,
    2701              :                                                                                                                          Edge * & shiftLowDimEl,
    2702              :                                                                                                                          std::vector<Edge*> & vecEdgsNotCutFaces
    2703              :                                                                                                                         )
    2704              : {
    2705              : 
    2706            0 :         if( uncuttingLowDimEl == nullptr )
    2707              :         {
    2708              :                 UG_LOG("null uncut" << std::endl );
    2709            0 :                 UG_THROW("null uncut" << std::endl );
    2710              :         }
    2711              : 
    2712            0 :         if( vecEndingFractManifNotCutting.size() == 0 )
    2713              :         {
    2714            0 :                 shiftLowDimEl = uncuttingLowDimEl;
    2715            0 :                 return true;
    2716              :         }
    2717              : 
    2718              :         std::vector<Edge*> vecEdgsCollectMulti;
    2719              : 
    2720              :         std::vector<Edge*> vecEdgsCollectSingle;
    2721              : 
    2722            0 :         for( SegLimSidesFractFace const & slsffUncl : vecSegmLimSiFFUnclosed )
    2723              :         {
    2724              : 
    2725              :                 Face * facUncl = slsffUncl.getManifElm();
    2726              : 
    2727            0 :                 for( Face * facNotCut : vecEndingFractManifNotCutting )
    2728              :                 {
    2729            0 :                         if( facNotCut == facUncl )
    2730              :                         {
    2731              :                                 EdgePair const & epU = slsffUncl.getPairLowElm();
    2732              : 
    2733            0 :                                 Edge * edgeOne = epU.first;
    2734            0 :                                 Edge * edgeTwo = epU.second;
    2735              : 
    2736            0 :                                 if( edgeOne != uncuttingLowDimEl )
    2737              :                                 {
    2738            0 :                                         vecEdgsCollectMulti.push_back(edgeOne);
    2739              : 
    2740              :                                         addElem(vecEdgsCollectSingle, edgeOne);
    2741              :                                 }
    2742              : 
    2743            0 :                                 if( edgeTwo != uncuttingLowDimEl )
    2744              :                                 {
    2745            0 :                                         vecEdgsCollectMulti.push_back(edgeTwo);
    2746              : 
    2747              :                                         addElem(vecEdgsCollectSingle,edgeTwo);
    2748              :                                 }
    2749              :                         }
    2750              :                 }
    2751              :         }
    2752              : 
    2753            0 :         if(    ( vecEdgsCollectMulti.size() != vecEdgsCollectSingle.size() * 2 - 1  )
    2754            0 :                 || ( vecEdgsCollectMulti.size() != ( ( vecSegmLimSiFFUnclosed.size() - 1 ) * 2 ) - 1  )
    2755            0 :                 || ( vecEdgsCollectSingle.size() != vecSegmLimSiFFUnclosed.size() - 1 )
    2756              :           )
    2757              :         {
    2758              :                 UG_LOG("Konzept der wilden Ecken schief gegangen " << std::endl);
    2759              : 
    2760              :                 UG_LOG("multi " << vecEdgsCollectMulti.size() << std::endl );
    2761              :                 UG_LOG("single " << vecEdgsCollectSingle.size() << std::endl );
    2762              :                 UG_LOG("segm uncl " << vecSegmLimSiFFUnclosed.size() << std::endl );
    2763              : 
    2764            0 :                 UG_THROW("Konzept der wilden Ecken schief gegangen " << std::endl);
    2765              :         }
    2766              : 
    2767              :         IndexType numShiftEdgFnd = 0;
    2768              : 
    2769            0 :         for( Edge * eS : vecEdgsCollectSingle )
    2770              :         {
    2771              :                 IndexType singleFoundInMulti = 0;
    2772              : 
    2773            0 :                 for( Edge * eM : vecEdgsCollectMulti )
    2774              :                 {
    2775            0 :                         if( eS == eM )
    2776            0 :                                 singleFoundInMulti++;
    2777              :                 }
    2778              : 
    2779            0 :                 if( singleFoundInMulti == 1 )
    2780              :                 {
    2781              :                         numShiftEdgFnd++;
    2782              : 
    2783            0 :                         shiftLowDimEl = eS;
    2784              :                 }
    2785            0 :                 else if( singleFoundInMulti == 2 )
    2786              :                 {
    2787            0 :                         vecEdgsNotCutFaces.push_back( eS );
    2788              :                 }
    2789              :                 else
    2790              :                 {
    2791              :                         UG_LOG("Edge not in useful number " << singleFoundInMulti << std::endl);
    2792            0 :                         UG_THROW("Edge not in useful number " << singleFoundInMulti << std::endl);
    2793              :                 }
    2794              : 
    2795              :         }
    2796              : 
    2797              :         return true;
    2798              : 
    2799              : //      IndexType edgeWasFound = 0;
    2800              : 
    2801              : //      for( SegLimSidesFractFace const & slsffUncl : vecSegmLimSiFFUnclosed )
    2802              : //      {
    2803              : //
    2804              : //              Face * facUncl = slsffUncl.getManifElm();
    2805              : //
    2806              : //              if( facUncl == endingFractManifNotCutting )
    2807              : //              {
    2808              : //                      EdgePair const & epU = slsffUncl.getPairLowElm();
    2809              : //
    2810              : //                      Edge * edgeOne = epU.first;
    2811              : //                      Edge * edgeTwo = epU.second;
    2812              : //
    2813              : //                      if( edgeOne == uncuttingLowDimEl )
    2814              : //                      {
    2815              : //                              shiftLowDimEl = edgeTwo;
    2816              : //                      }
    2817              : //                      else if( edgeTwo == uncuttingLowDimEl )
    2818              : //                      {
    2819              : //                              shiftLowDimEl = edgeOne;
    2820              : //                      }
    2821              : //                      else
    2822              : //                      {
    2823              : //                              UG_LOG("No edge found uncutting shift?" << std::endl);
    2824              : //                              UG_THROW("No edge found uncutting shift?" << std::endl);
    2825              : //                      }
    2826              : //
    2827              : //                      edgeWasFound++;
    2828              : //
    2829              : //              }
    2830              : //      }
    2831              : //
    2832              : //      if( edgeWasFound == 0 )
    2833              : //      {
    2834              : //              UG_LOG("NO shift edge " << std::endl);
    2835              : //              return false;
    2836              : //      }
    2837              : //      else if( edgeWasFound == 1 )
    2838              : //      {
    2839              : //              return true;
    2840              : //      }
    2841              : //      if( edgeWasFound > 1 )
    2842              : //      {
    2843              : //              UG_LOG("Many shift edges " << edgeWasFound << std::endl);
    2844              : //              return false;
    2845              : //      }
    2846              : 
    2847              :         UG_LOG("Cannot come here at this edge" << std::endl);
    2848              : 
    2849              :         return false;
    2850              : 
    2851            0 : }
    2852              : 
    2853              : //////////////////////////////////////////////////////////////////
    2854              : 
    2855              : template<typename ELMTYP>
    2856            0 : bool ArteExpandFracs3D::checkIfContentUnique( std::vector<ELMTYP> const & vecTest, std::vector<ELMTYP> & content, IndexType mandatoryDifferentElems )
    2857              : {
    2858            0 :         if( vecTest.size() == 0 )
    2859              :         {
    2860              :                 UG_LOG("zero vector testing nonsense" << std::endl);
    2861            0 :                 UG_THROW("zero vector testing nonsense" << std::endl);
    2862              :         }
    2863              : 
    2864            0 :         std::vector<ELMTYP> vecTestCop = vecTest; // copy
    2865              : 
    2866            0 :         while( vecTestCop.size() != 0 )
    2867              :         {
    2868            0 :                 ELMTYP elmCont = vecTestCop[0];
    2869              : 
    2870            0 :                 content.push_back(elmCont);
    2871              : 
    2872            0 :                 for( typename std::vector<ELMTYP>::iterator itEl = vecTestCop.begin(); itEl != vecTestCop.end(); )
    2873              :                 {
    2874            0 :                         ELMTYP elmTest = *itEl;
    2875              : 
    2876            0 :                         if( elmCont == elmTest )
    2877              :                         {
    2878              :                                 itEl = vecTestCop.erase(itEl);
    2879              :                         }
    2880              :                         else
    2881              :                                 ++itEl;
    2882              :                 }
    2883              : 
    2884              :         }
    2885              : 
    2886            0 :         return ( mandatoryDifferentElems == content.size() );
    2887            0 : }
    2888              : 
    2889              : //////////////////////////////////////////////////////////////////
    2890              : 
    2891              : template< bool FACES_HAVE_SAME_SUDO >
    2892            0 : bool ArteExpandFracs3D::fractFacesAreNeighboured( SegLimSidesFractFace const & fractFaceOne,
    2893              :                                                                                                   SegLimSidesFractFace const & fractFaceTwo,
    2894              :                                                                                                   Edge * & commonEdge
    2895              :                                                                                                 )
    2896              : {
    2897            0 :         commonEdge = nullptr; // general case
    2898              : 
    2899              :         bool facesHaveSameSudo = FACES_HAVE_SAME_SUDO;
    2900              : 
    2901              :         // exclude that the elements are the same
    2902              : 
    2903              :         Face * facOne = fractFaceOne.getManifElm();
    2904              :         Face * facTwo = fractFaceTwo.getManifElm();
    2905              : 
    2906            0 :         if( facOne == facTwo )
    2907              :         {
    2908              :                 UG_LOG("Faces coincide" << std::endl);
    2909            0 :                 return false;
    2910              :         }
    2911              : 
    2912              :         EdgePair const & edgesFacOne = fractFaceOne.getPairLowElm();
    2913              :         EdgePair const & edgesFacTwo = fractFaceTwo.getPairLowElm();
    2914              : 
    2915              :         Edge * edgeOneFrst = edgesFacOne.first;
    2916              :         Edge * edgeOneScnd = edgesFacOne.second;
    2917              : 
    2918              :         Edge * edgeTwoFrst = edgesFacTwo.first;
    2919              :         Edge * edgeTwoScnd = edgesFacTwo.second;
    2920              : 
    2921            0 :         bool edgeCondA = ( edgeOneFrst == edgeTwoFrst );
    2922            0 :         bool edgeCondB = ( edgeOneFrst == edgeTwoScnd );
    2923            0 :         bool edgeCondC = ( edgeOneScnd == edgeTwoFrst );
    2924            0 :         bool edgeCondD = ( edgeOneScnd == edgeTwoScnd );
    2925              : 
    2926              : 
    2927              :         bool fractFacsNeighbr = (    edgeCondA
    2928            0 :                                                           || edgeCondB
    2929              :                                                           || edgeCondC
    2930            0 :                                                           || edgeCondD
    2931              :                                                         );
    2932              : 
    2933              :         IndexType sudoOne = fractFaceOne.getSudo();
    2934              :         IndexType sudoTwo = fractFaceTwo.getSudo();
    2935              : 
    2936              :         bool sudosCoincide = ( sudoOne == sudoTwo );
    2937              : 
    2938            0 :         bool necessarySudoProperty = ( facesHaveSameSudo == sudosCoincide );
    2939              : 
    2940            0 :         bool neighbrsWithRequestedSudo = ( fractFacsNeighbr && necessarySudoProperty );
    2941              : 
    2942            0 :         if( neighbrsWithRequestedSudo )
    2943              :         {
    2944            0 :                 if( edgeCondA || edgeCondB )
    2945              :                 {
    2946            0 :                         commonEdge = edgeOneFrst;
    2947              :                 }
    2948            0 :                 else if( edgeCondC || edgeCondD )
    2949              :                 {
    2950            0 :                         commonEdge = edgeOneScnd;
    2951              :                 }
    2952              : 
    2953            0 :                 if( commonEdge == nullptr )
    2954              :                 {
    2955              :                         UG_LOG("COMMON NULL " << std::endl);
    2956            0 :                         UG_THROW("COMMON NULL " << std::endl);
    2957              :                 }
    2958              :                 else
    2959              :                 {
    2960            0 :                         UG_LOG("COORDINATES NOT NULL " << CalculateCenter( commonEdge, m_aaPos ) << std::endl );
    2961              :                 }
    2962              :         }
    2963              : 
    2964              :         return neighbrsWithRequestedSudo;
    2965              : }
    2966              : 
    2967              : 
    2968              : //////////////////////////////////////////////////////////////////
    2969              : 
    2970              : 
    2971              : #if 0
    2972              : bool ArteExpandFracs3D::detectEndingCrossingClefts()
    2973              : {
    2974              : //      bool unclosedFracFacesPresent = false;
    2975              : //
    2976              : //      for( VertexIterator iter = m_sel.begin<Vertex>(); iter != m_sel.end<Vertex>(); ++iter)
    2977              : //      {
    2978              : //              Vertex* vrt = *iter;
    2979              : //
    2980              : //              IndexType shiFraFac = shiftUnclosedFracFacesToUnclosedFractFaces( vrt );
    2981              : //
    2982              : //              UG_LOG("shifted frac faces at " << m_aaPos[vrt] << " -> " << shiFraFac << std::endl);
    2983              : //
    2984              : //              if( shiFraFac > 0 )
    2985              : //                      unclosedFracFacesPresent = true;
    2986              : //
    2987              : ////            constexpr bool d_highlightVrtcsWithShifts = false;
    2988              : ////
    2989              : ////            if( d_highlightVrtcsWithShifts )
    2990              : ////            {
    2991              : ////                    if( shiFraFac > 0 )
    2992              : ////                    {
    2993              : ////                            IndexType sudoNum = m_sh.num_subsets();
    2994              : ////
    2995              : ////                            m_sh.assign_subset(vrt, sudoNum );
    2996              : ////                    }
    2997              : ////            }
    2998              : //      }
    2999              : 
    3000              :         IndexType numEndingCrossingClefts = 0;
    3001              : 
    3002              :         std::vector<Face*> m_d_endingCrossingCleftFaces;
    3003              : 
    3004              :         std::vector<Vertex*> m_d_endingCrossingCleftVrtcs;
    3005              : 
    3006              : 
    3007              : //      for( VertexIterator iter = m_sel.begin<Vertex>(); iter != m_sel.end<Vertex>(); ++iter)
    3008              : //      {
    3009              : //              Vertex* vrt = *iter;
    3010              : //
    3011              : //
    3012              : //
    3013              : //      }
    3014              : 
    3015              : 
    3016              : 
    3017              :         // TODO FIXME unterscheide Faces entlang der expandierten Kreuzungskluft,
    3018              :         // mit 2 Knoten an Kreuzungspunkten, ein Knoten voll expandiert für beide subsets
    3019              :         // von solchen, die in der Luft hängen am Ende der Kluft, wo nur die durchgehende Kluft expandiert
    3020              : 
    3021              :         // TODO FIXME need to detect attached faces from the durchgehende cleft which gets expanded
    3022              :         // as specific structures needed also there
    3023              : 
    3024              :         // TODO FIXME auch die Kante, die an dem auslaufenden Face entlang geht im Schnitt mit dem ausgedehnten,
    3025              :         // per edge attachment markieren! bool
    3026              :         // und die anhängenden faces der kreuzenden durchgehenden Kluft ebenso markieren irgendwie per face attachment bool
    3027              : 
    3028              : 
    3029              : 
    3030              : 
    3031              : #if 1
    3032              : 
    3033              :         IndexType unclosedFracFacesFound = 0;
    3034              : 
    3035              :         for(size_t i_fi = 0; i_fi < m_fracInfos.size(); ++i_fi )
    3036              :         {
    3037              : 
    3038              :                 int fracIndSudo = m_fracInfos[i_fi].subsetIndex;
    3039              : 
    3040              :                 for( FaceIterator iter = m_sh.begin<Face>(fracIndSudo); iter != m_sh.end<Face>(fracIndSudo); ++iter )
    3041              :                 {
    3042              :                         Face* fac = *iter;
    3043              : 
    3044              :                         UG_LOG("Check for unclosed frac faces " << CalculateCenter(fac, m_aaPos) << std::endl);
    3045              : 
    3046              :                         if( m_aaMarkFaceHasUnclosedFracSideB[fac] )
    3047              :                         {
    3048              :                                 unclosedFracFacesFound++;
    3049              : 
    3050              : //                              m_sh.assign_subset( fac, m_sh.num_subsets());
    3051              :                         }
    3052              : 
    3053              :                 }
    3054              : 
    3055              :         }
    3056              : 
    3057              :         if( unclosedFracFacesFound > 0 ) // || unclosedFracFacesPresent )
    3058              :         {
    3059              :                 UG_LOG("unclosed Frac faces " << unclosedFracFacesFound << std::endl);
    3060              : //              return false;
    3061              :         }
    3062              : 
    3063              : //      return true;
    3064              : 
    3065              : 
    3066              :         //  wieso die ending crossing cleft faces nicht aus den Segmenten raus holen,
    3067              :         // und zwar aus den ungeschlossenen Faces, die im Segment liegen?
    3068              :         // müssen doch dieselben sein, dann sollte die komische Prozedur hier unnötig werden!!!
    3069              : 
    3070              : 
    3071              : //      UG_THROW("KÄSE" << std::endl);
    3072              : 
    3073              :         for(size_t i_fi = 0; i_fi < m_fracInfos.size(); ++i_fi )
    3074              :         {
    3075              :                 int fracIndSudo = m_fracInfos[i_fi].subsetIndex;
    3076              : 
    3077              :                 for( FaceIterator iter = m_sh.begin<Face>(fracIndSudo); iter != m_sh.end<Face>(fracIndSudo); iter++ )
    3078              :                 {
    3079              :                         Face* fac = *iter;
    3080              : 
    3081              :                         UG_LOG("Detect for unclosed ending cleft frac faces " << CalculateCenter(fac, m_aaPos) << std::endl);
    3082              : 
    3083              :                         if( m_aaMarkFaceHasUnclosedFracSideB[fac] )
    3084              :                         {
    3085              : 
    3086              :                                 // figure out the vertice(s) where the face is unclosed
    3087              :                                 // check if at one of these vertices, two fractures are crossing and one ending
    3088              :                                 // by checking if there are at least two segments as precondition, else no matter
    3089              : 
    3090              :                                 std::vector<Vertex *> assoVrt;
    3091              : 
    3092              :                                 CollectVertices(assoVrt, m_grid, fac);
    3093              : 
    3094              :                                 for( Vertex * vrt : assoVrt )
    3095              :                                 {
    3096              :                                         if( m_aaMarkVrtxHasUnclosedFracB[vrt] )
    3097              :                                         {
    3098              :                                                 VecSegmentVolElmInfo & vecSegVolElmInf = m_accsAttVecSegVolElmInfo[vrt];
    3099              : 
    3100              :                                                 if( vecSegVolElmInf.size() > 1 ) // expansion takes place here
    3101              :                                                 {
    3102              : //                                                      m_sh.assign_subset(fac,m_sh.num_subsets());
    3103              :                                                         numEndingCrossingClefts++;
    3104              :                                                         m_d_endingCrossingCleftFaces.push_back(fac);
    3105              :                                                         m_d_endingCrossingCleftVrtcs.push_back(vrt);
    3106              :                                                         // TODO FIXME vielleicht eine Klasse, wo die Faces und Vertices einer
    3107              :                                                         // jeweiligen ending Crossing Cleft Stelle zusammengefasst werden?
    3108              :                                                         // statt unabhängige Listen? gemeinsame Liste?
    3109              :                                                 }
    3110              : 
    3111              :                                         }
    3112              :                                 }
    3113              : 
    3114              : 
    3115              :                         }
    3116              : 
    3117              :                 }
    3118              : 
    3119              :         }
    3120              : 
    3121              : 
    3122              :         UG_LOG("detected ending crossing cleft faces " << numEndingCrossingClefts << std::endl);
    3123              : 
    3124              :         if( numEndingCrossingClefts == 0 )
    3125              :                 return true;
    3126              : 
    3127              :         // debug for ending crossing clefts
    3128              : 
    3129              :         for( Face * fac : m_d_endingCrossingCleftFaces )
    3130              :         {
    3131              :                 m_sh.assign_subset( fac, m_sh.num_subsets());
    3132              : 
    3133              :         }
    3134              : 
    3135              :         for( Vertex * vrt : m_d_endingCrossingCleftVrtcs )
    3136              :         {
    3137              :                 m_sh.assign_subset( vrt, m_sh.num_subsets());
    3138              :         }
    3139              : 
    3140              : #endif
    3141              : 
    3142              : 
    3143              :         return false;
    3144              : 
    3145              : 
    3146              : 
    3147              : }
    3148              : 
    3149              : #endif
    3150              : 
    3151              : ////////////////////////////////////////////////////////////////////
    3152              : 
    3153              : #if 0
    3154              : bool ArteExpandFracs3D::detectEndingCrossingClefts()
    3155              : {
    3156              : 
    3157              :         //  wieso die ending crossing cleft faces nicht aus den Segmenten raus holen,
    3158              :         // und zwar aus den ungeschlossenen Faces, die im Segment liegen?
    3159              :         // müssen doch dieselben sein, dann sollte die komische Prozedur hier unnötig werden!!!
    3160              : 
    3161              :         IndexType numEndingCrossingClefts = 0;
    3162              : 
    3163              :         std::vector<Face*> m_d_endingCrossingCleftFaces;
    3164              : 
    3165              :         std::vector<Vertex*> m_d_endingCrossingCleftVrtcs;
    3166              : 
    3167              : //      UG_THROW("KÄSE" << std::endl);
    3168              : 
    3169              :         for(size_t i_fi = 0; i_fi < m_fracInfos.size(); ++i_fi )
    3170              :         {
    3171              :                 int fracIndSudo = m_fracInfos[i_fi].subsetIndex;
    3172              : 
    3173              :                 for( FaceIterator iter = m_sh.begin<Face>(fracIndSudo); iter != m_sh.end<Face>(fracIndSudo); iter++ )
    3174              :                 {
    3175              :                         Face* fac = *iter;
    3176              : 
    3177              :                         UG_LOG("Detect for unclosed ending cleft frac faces " << CalculateCenter(fac, m_aaPos) << std::endl);
    3178              : 
    3179              :                         if( m_aaMarkFaceHasUnclosedFracSideB[fac] )
    3180              :                         {
    3181              : 
    3182              :                                 // figure out the vertice(s) where the face is unclosed
    3183              :                                 // check if at one of these vertices, two fractures are crossing and one ending
    3184              :                                 // by checking if there are at least two segments as precondition, else no matter
    3185              : 
    3186              :                                 std::vector<Vertex *> assoVrt;
    3187              : 
    3188              :                                 CollectVertices(assoVrt, m_grid, fac);
    3189              : 
    3190              :                                 for( Vertex * vrt : assoVrt )
    3191              :                                 {
    3192              :                                         if( m_aaMarkVrtxHasUnclosedFracB[vrt] )
    3193              :                                         {
    3194              :                                                 VecSegmentVolElmInfo & vecSegVolElmInf = m_accsAttVecSegVolElmInfo[vrt];
    3195              : 
    3196              :                                                 if( vecSegVolElmInf.size() > 1 ) // expansion takes place here
    3197              :                                                 {
    3198              : //                                                      m_sh.assign_subset(fac,m_sh.num_subsets());
    3199              :                                                         numEndingCrossingClefts++;
    3200              :                                                         m_d_endingCrossingCleftFaces.push_back(fac);
    3201              :                                                         m_d_endingCrossingCleftVrtcs.push_back(vrt);
    3202              :                                                         // TODO FIXME vielleicht eine Klasse, wo die Faces und Vertices einer
    3203              :                                                         // jeweiligen ending Crossing Cleft Stelle zusammengefasst werden?
    3204              :                                                         // statt unabhängige Listen? gemeinsame Liste?
    3205              :                                                 }
    3206              : 
    3207              :                                         }
    3208              :                                 }
    3209              : 
    3210              : 
    3211              :                         }
    3212              : 
    3213              :                 }
    3214              : 
    3215              :         }
    3216              : 
    3217              :         // TODO FIXME m_d_endingCrossingCleftVrtcs      m_d_endingCrossingCleftFaces globale member vielleicht?
    3218              : 
    3219              : #if 0
    3220              : //      for( VertexIterator iterV = m_sel.begin<Vertex>(); iterV != m_sel.end<Vertex>(); iterV++ )
    3221              :         for( Vertex * vrt : m_d_endingCrossingCleftVrtcs )
    3222              :         {
    3223              : //              Vertex * vrt = *iterV;
    3224              : 
    3225              :                 // search neigbours of ending crossing cleft faces
    3226              : 
    3227              :                 if( m_aaMarkVrtxHasUnclosedFracB[vrt] )
    3228              :                 {
    3229              :                         VecSegmentVolElmInfo const & vecSegVolElmInf = m_accsAttVecSegVolElmInfo[vrt];
    3230              : 
    3231              :                         for( SegmentVolElmInfo const & svei : vecSegVolElmInf )
    3232              :                         {
    3233              :                                 for( AttachedVolumeElemInfo const & attVolEI : svei )
    3234              :                                 {
    3235              :                                         VecAttachedFractFaceEdgeSudo vecAttFracFace = attVolEI.getVecFractManifElem();
    3236              :                                         // die sind alle von den echten das Segment begrenzenden Faces
    3237              : 
    3238              :                                         for( AttachedFractFaceEdgeSudo & afes : vecAttFracFace )
    3239              :                                         {
    3240              :                                                 Face * faceSegmLim = afes.getManifElm();
    3241              : 
    3242              :                                                 IndexType sudoSegmLim = afes.getSudo();
    3243              : 
    3244              :                                                 std::pair<Edge*,Edge*> const & edgePair = afes.getPairLowElm();
    3245              : 
    3246              :                                                 // figure out neighbours of ending crossing cleft faces at ending node
    3247              : 
    3248              :                                                 // rule out free edge
    3249              : 
    3250              :                                                 Edge * freeEdge = nullptr;
    3251              :                                                 Edge * boundedEdge = nullptr;
    3252              : 
    3253              :                                                 for( Face * eccf : m_d_endingCrossingCleftFaces )
    3254              :                                                 {
    3255              :                                                         if( FaceContains( eccf, vrt ) )
    3256              :                                                         {
    3257              :                                                                 if( eccf != fac )
    3258              :                                                                 {
    3259              :                                                                         if( FaceContains( eccf, edgePair.first ) || FaceContains( eccf, edgePair.second ) )
    3260              :                                                                         {
    3261              : 
    3262              :                                                                         }
    3263              :                                                                 }
    3264              :                                                         }
    3265              :                                                 }
    3266              : //                                              if( )
    3267              :                                         }
    3268              : 
    3269              :                                 }
    3270              : 
    3271              : 
    3272              :                         }
    3273              :                 }
    3274              :                 else
    3275              :                 {
    3276              :                         UG_LOG("only ending crossing cleft vertices allowed here" << std::endl);
    3277              :                         UG_THROW("only ending crossing cleft vertices allowed here" << std::endl);
    3278              :                         return false;
    3279              :                 }
    3280              : 
    3281              :         }
    3282              : 
    3283              : #endif
    3284              : 
    3285              : 
    3286              :         UG_LOG("detected ending crossing cleft faces " << numEndingCrossingClefts << std::endl);
    3287              : 
    3288              :         if( numEndingCrossingClefts == 0 )
    3289              :                 return true;
    3290              : 
    3291              :         // debug for ending crossing clefts
    3292              : 
    3293              :         for( Face * fac : m_d_endingCrossingCleftFaces )
    3294              :         {
    3295              :                 m_sh.assign_subset( fac, m_sh.num_subsets());
    3296              : 
    3297              :         }
    3298              : 
    3299              :         for( Vertex * vrt : m_d_endingCrossingCleftVrtcs )
    3300              :         {
    3301              :                 m_sh.assign_subset( vrt, m_sh.num_subsets());
    3302              :         }
    3303              : 
    3304              :         // TODO FIXME unterscheide Faces entlang der expandierten Kreuzungskluft,
    3305              :         // mit 2 Knoten an Kreuzungspunkten, ein Knoten voll expandiert für beide subsets
    3306              :         // von solchen, die in der Luft hängen am Ende der Kluft, wo nur die durchgehende Kluft expandiert
    3307              : 
    3308              :         // TODO FIXME need to detect attached faces from the durchgehende cleft which gets expanded
    3309              :         // as specific structures needed also there
    3310              : 
    3311              :         // TODO FIXME auch die Kante, die an dem auslaufenden Face entlang geht im Schnitt mit dem ausgedehnten,
    3312              :         // per edge attachment markieren! bool
    3313              :         // und die anhängenden faces der kreuzenden durchgehenden Kluft ebenso markieren irgendwie per face attachment bool
    3314              : 
    3315              :         return false;
    3316              : }
    3317              : 
    3318              : #endif
    3319              : 
    3320              : //////////////////////////////////////////////////////////////////
    3321              : 
    3322              : // TODO FIXME diese Funktion macht nur in Teilen das richtige
    3323              : // die ungeschlossenen Faces zeigen an, dass eine Kluft hier endet
    3324              : // wird bisher nicht berücksichtigt
    3325              : // irgendwie muss das markiert werden, damit die Kluft, die zu Ende geht.
    3326              : // im Durchstich trotzdem berücksichtigt wird
    3327            0 : ArteExpandFracs3D::IndexType ArteExpandFracs3D::shiftUnclosedFracFacesToUnclosedFractFaces( Vertex * const & vrt )
    3328              : {
    3329              :         IndexType shiftedFracFaces = 0;
    3330              : 
    3331              :         // TODO FIXME still to be implemented - shift those fracture faces which appear
    3332              :         // twice in the segment volumes, i.e. which are part of two volumes of the
    3333              :         // segment, i.e. which touch each other, but are not closed,
    3334              :         // shift them to the general faces, to avoid that they are taken into account
    3335              :         // for the creation of new vertices, they must not have any influence
    3336              : 
    3337              :         UG_LOG("SHIFT FRAC 2 GENER" << std::endl);
    3338              : 
    3339            0 :         VecSegmentVolElmInfo & vecSegVolElmInf = m_accsAttVecSegVolElmInfo[vrt];
    3340              : 
    3341              :         IndexType segmentNumber = 0;
    3342              : 
    3343              : 
    3344              : 
    3345            0 :         for( SegmentVolElmInfo & svei : vecSegVolElmInf )
    3346              :         {
    3347              : //              VecAttachedFractFaceEdgeSudo vecAttFractList;
    3348              : 
    3349            0 :                 for( AttachedVolumeElemInfo & attVolEIOne : svei )
    3350              :                 {
    3351              :                         VecAttachedFractFaceEdgeSudo vecAttFracFaceOne = attVolEIOne.getVecFractManifElem();
    3352              : 
    3353            0 :                         for( AttachedVolumeElemInfo & attVolEITwo : svei )
    3354              :                         {
    3355            0 :                                 if( ! attVolEIOne.hasSameFulldimElem( attVolEITwo ) )
    3356              :                                 {
    3357              :                                         VecAttachedFractFaceEdgeSudo vecAttFracFaceTwo = attVolEITwo.getVecFractManifElem();
    3358              : 
    3359            0 :                                         for( AttachedFractFaceEdgeSudo & afesOne : vecAttFracFaceOne )
    3360              :                                         {
    3361            0 :                                                 for( AttachedFractFaceEdgeSudo & afesTwo : vecAttFracFaceTwo )
    3362              :                                                 {
    3363              :                                                         if( afesOne.testIfEquals( afesTwo ) )
    3364              :                                                         {
    3365              :                                                                 // beide in die generellen Faces verschieben!
    3366              : 
    3367            0 :                                                                 if( ! attVolEIOne.searchFractManifElem( afesOne, true ) )
    3368              :                                                                 {
    3369            0 :                                                                         UG_THROW("im einen nicht gefunden "<< std::endl);
    3370              :                                                                 }
    3371              : 
    3372            0 :                                                                 if( ! attVolEITwo.searchFractManifElem( afesTwo, true ) )
    3373              :                                                                 {
    3374            0 :                                                                         UG_THROW("im anderen nicht gefunden "<< std::endl);
    3375              :                                                                 }
    3376              : 
    3377            0 :                                                                 shiftedFracFaces++;
    3378              : 
    3379              : //                                                              Face * unclosedFace = afesOne.getManifElm();
    3380              : //                                                              // tested if same as that one from afesTwo
    3381              : //
    3382              : ////                                                            m_aaMarkFaceHasUnclosedFracSideB[ unclosedFace ] = true;
    3383              : //
    3384              : //                                                              UG_LOG("unclosed face " << CalculateCenter( unclosedFace, m_aaPos ) << std::endl);
    3385              : 
    3386              : //                                                              m_sh.assign_subset( unclosedFace, m_sh.num_subsets());
    3387              : 
    3388              : //                                                              m_aaMarkVrtxHasUnclosedFracB[vrt] = true;
    3389              : 
    3390              :                                                                 //  added vertex attachment that knows if at vertex there is an unclosed fracture
    3391              : 
    3392              : 
    3393              :                                                         }
    3394              :                                                 }
    3395              :                                         }
    3396            0 :                                 }
    3397              :                         }
    3398              : 
    3399              : 
    3400              : //                      for( AttachedFractFaceEdgeSudo & affe : nextVolFacs )
    3401              : //                      {
    3402              : //                              vecAttFractList.push_back( affe );
    3403              : //                      }
    3404              :                         // create a full chain of all fracture faces, and if one appears twice, shift it for both
    3405              :                         // volumes where it is in to the general faces, i.e. count after establishing, and when twice,
    3406              :                         // then shift
    3407            0 :                 }
    3408              :         }
    3409              : 
    3410              :         UG_LOG("SHIFT FRAC 2 GENER" << std::endl);
    3411              : 
    3412              : 
    3413              : 
    3414            0 :         return shiftedFracFaces;
    3415              : }
    3416              : 
    3417              : //////////////////////////////////////////////////////////////////
    3418              : 
    3419              : 
    3420              : 
    3421            0 : bool ArteExpandFracs3D::seletForSegmented()
    3422              : {
    3423            0 :         for( VertexIterator iter = m_sel.begin<Vertex>(); iter != m_sel.end<Vertex>(); ++iter)
    3424              :         {
    3425              :                 Vertex* vrt = *iter;
    3426              : 
    3427              : #if 0
    3428              : 
    3429              :                 bool wahl = true;
    3430              : 
    3431              :                 // TODO FIXME
    3432              :                 // hier den Stammi-bene Algorithmus einfügen
    3433              :                 // Search the merged manifold interatively between each basic element
    3434              :                 // dazu noch für boundary faces ein eigenes member einführen,
    3435              :                 // das vom Typ General statt fracture manifold ist, aber sonst wie general
    3436              :                 // später wirken die boundary faces wie eine fracture, die aber
    3437              :                 // um den Wert null nur verschoben wird
    3438              :                 // die Anzahl der Segmente bestimmt, ob der Vertex gewählt wird
    3439              :                 // damit er gewählt wird, muss mehr als ein Segment vorhanden sein
    3440              : 
    3441              :                 auto & vrtxFracPrps = m_aaMarkVrtVFP[ vrt ];
    3442              : 
    3443              : //              bool isBnd = m_aaMarkVrtVFP[ vrt ].getIsBndFracVertex();
    3444              :                 bool isBnd = vrtxFracPrps.getIsBndFracVertex();
    3445              : //              auto numCrosFrac = m_aaMarkVrtVFP[ vrt ].getNumberFracEdgesInVertex();
    3446              : 
    3447              :                 VertxFracPropts::VrtxFracStatus vfpStatus =  vrtxFracPrps.getVrtxFracStatus();
    3448              : 
    3449              :                 if( vfpStatus == VertxFracPropts::noFracSuDoAtt )
    3450              :                         UG_THROW("vertex selected and no frac " << std::endl);
    3451              : 
    3452              :                 // TODO FIXME das ist richtig für den 2D Fall, aber passt das auch im 3D Fall???? nein, da SudoFrac Zahl nötig
    3453              : //              if( ! isBnd && numCrosFrac == 1 )
    3454              : //              if( ! isBnd && vfpStatus == VertxFracPropts::oneFracSuDoAtt && )
    3455              :                 // TODO FIXME was, wenn ein Teil geschlossen ist der fractures, und ein anderer nicht???
    3456              :                 //static_assert(false);
    3457              : 
    3458              : 
    3459              :                 // bestimmen, ob die vertizes der fracture vertizes von ihrer subdomain komplett umzingelt werden
    3460              :                 // muss vor  hier geklärt werden!!!
    3461              : 
    3462              : //              VecPairSudoBool sudoIsSourrounded;
    3463              : 
    3464              : 
    3465              : 
    3466              :                 bool allClosed = false;
    3467              : 
    3468              :                 allClosed = isVrtxSurroundedByFracFaces( vrt, vrtxFracPrps ); //, sudoIsSourrounded );
    3469              : //                      // case boundary: figure out if the vertex is surrounded by frac faces of which two end in
    3470              : //                      // boundary edges, similar the case when the boundary face has itself two
    3471              : //                      // boundary edges, where the vertex is connected to both of them, then it is easy
    3472              : 
    3473              : //              if( ! allClosed )
    3474              : //                      return false;
    3475              : 
    3476              : //              return true;
    3477              : 
    3478              : //              if( ! isBnd )
    3479              : //              {
    3480              : //                      UG_LOG("test if closed" << std::endl);
    3481              : //
    3482              : ////                    m_sh.assign_subset(vrt,m_sh.num_subsets());
    3483              : //
    3484              : ////                    UG_LOG("test if closed assign" << std::endl);
    3485              : //
    3486              : //
    3487              : //              }
    3488              : //              else
    3489              : //              {
    3490              : //
    3491              : //
    3492              : //
    3493              : ////                    allClosed =
    3494              : //              }
    3495              : //              // TODO FIXME auch bei einer boundary muss das gemacht werden!
    3496              : 
    3497              :                 UG_LOG("getestet if closed " << m_aaPos[vrt] << std::endl);
    3498              : 
    3499              : 
    3500              : //              return true;
    3501              : 
    3502              :                 if( allClosed == vrtxFracPrps.getInfoAllFracturesSameClosedState<false>() )
    3503              :                         UG_THROW("da ist was schief gegangen " << std::endl);
    3504              : 
    3505              :                 // TODO FIXME ist das so richtig? kann sein, dass das zu vereinfacht ist!!!!!
    3506              :                 // sudo is suourrounded muss übertragen werden TODO FIXME
    3507              : //              if( ! isBnd && vrtxFracPrps.getInfoAllFracturesSameClosedState<false>() )
    3508              :                 // das !isBnd im 2D Fall wichtig, hier bestimmt auch, wie verallgemeinern?
    3509              :                 // bei mehreren subdoms eventuell komplizierter, kommt aber hoffentlich am Rand nicht vor......
    3510              :                 if( vrtxFracPrps.getInfoAllFracturesSameClosedState<false>() )
    3511              :                 {
    3512              :                         wahl = false;
    3513              :                 }
    3514              : 
    3515              : #else
    3516              : 
    3517              :                 VecSegmentVolElmInfo & vecSegVolElmInf = m_accsAttVecSegVolElmInfo[vrt];
    3518              : 
    3519              :                 auto & vrtxFracPrps = m_aaMarkVrtVFP[ vrt ];
    3520              : 
    3521              : //              bool isBnd = m_aaMarkVrtVFP[ vrt ].getIsBndFracVertex();
    3522              :                 bool isBnd = vrtxFracPrps.getIsBndFracVertex();
    3523              : 
    3524              : //              bool wahl = ( vecSegVolElmInf.size() > 1 );
    3525              : //              bool wahl = ( vecSegVolElmInf.size() > 1 && ! isBnd );
    3526            0 :                 bool wahl = ( vecSegVolElmInf.size() > 1 );
    3527              :                 // TODO FIXME danach vielleicht auch fuer boundary wieder selektieren
    3528              :                 // sobald die Boundary Behandlung wie Pseudo Fracture mit Expansion null
    3529              :                 // aber solange die bounaries nicht behandelt werden, führt
    3530              :                 // die Selektion der Boundary Vertizes zu Problemen
    3531              : 
    3532              : #endif
    3533              : 
    3534              : 
    3535              : //              UG_LOG("SELEKTIERE " << m_aaPos[vrt] << " -> " << vrtxFracPrps.getInfoAllFracturesSameClosedState<false>() << std::endl);
    3536              : 
    3537            0 :                 UG_LOG("SELEKTIERE " << m_aaPos[vrt] << " -> " << wahl << std::endl);
    3538              : 
    3539              : 
    3540              :                 // was, wenn numCrossFrac == 0 ist?
    3541              :                 // wieso werden die boundary vrt ausgeschlossen, oder sollen die nicht ausgeschlossen werden?
    3542              :                 // schon im 2D Fall unklar, hier noch wirrer!!! TODO FIXME
    3543              : 
    3544            0 :                 if( wahl )
    3545              : //              if( m_aaMarkVrtVFP[vrt].getNumberFracEdgesInVertex() > 1 ) // TODO FIXME stimmt das so?
    3546              :                 {
    3547              :                         //      select all associated edges, faces and volumes
    3548            0 :                         m_sel.select( m_grid.associated_edges_begin(vrt), m_grid.associated_edges_end(vrt) );
    3549            0 :                         m_sel.select( m_grid.associated_faces_begin(vrt), m_grid.associated_faces_end(vrt) );
    3550            0 :                         m_sel.select( m_grid.associated_volumes_begin(vrt), m_grid.associated_volumes_end(vrt) );
    3551              : 
    3552              :                         std::vector<Edge*> assoEdg;
    3553              :                         std::vector<Face*> assoFac;
    3554              : //                      std::vector<Volume*> assoVol;
    3555              : //                      VecAttachedVolumeElemInfo assoVolElemInfo;
    3556              : 
    3557            0 :                         for( std::vector<Edge *>::iterator iterEdg = m_grid.associated_edges_begin(vrt);
    3558            0 :                                                                                            iterEdg != m_grid.associated_edges_end(vrt);
    3559              :                                                                                            iterEdg++ )
    3560              :                         {
    3561            0 :                                 assoEdg.push_back(*iterEdg);
    3562              :                         }
    3563              : 
    3564            0 :                         for( std::vector<Face *>::iterator iterFac = m_grid.associated_faces_begin(vrt);
    3565            0 :                                                                                            iterFac != m_grid.associated_faces_end(vrt);
    3566              :                                                                                            iterFac++ )
    3567              :                         {
    3568            0 :                                 assoFac.push_back(*iterFac);
    3569              :                         }
    3570              : 
    3571              :                         // TODO FIXME das nach oben verschieben, wo der Stammi Bene Algo sein soll
    3572              :                         // die asso edges und faces brauchen wir vielleicht gar nicht
    3573              :                         // bzw asso edges und asso faces können hier bleiben wo gewählt wird
    3574              :                         // die assoVolElemInfo wird schon oben erzeugt vor der Wahl
    3575              :                         // und dann wird die danach folgende Loop Info
    3576              : //                      for( std::vector<Volume *>::iterator iterVol = m_grid.associated_volumes_begin(vrt);
    3577              : //                                                                                               iterVol != m_grid.associated_volumes_end(vrt);
    3578              : //                                                                                               iterVol++ )
    3579              : //                      {
    3580              : //                              assoVol.push_back(*iterVol);
    3581              : //
    3582              : //                              AttachedVolumeElemInfo avei(*iterVol);
    3583              : //
    3584              : //                              assoVolElemInfo.push_back(avei);
    3585              : //                      }
    3586              : 
    3587            0 :                         m_aaVrtInfoAssoEdges[vrt] = assoEdg;
    3588            0 :                         m_aaVrtInfoAssoFaces[vrt] = assoFac;
    3589              : //                      m_aaVrtInfoAssoVols[vrt] = assoVol;
    3590              : //                      m_aaVolElmInfo[vrt] = assoVolElemInfo;
    3591              : 
    3592            0 :                 }
    3593              :         }
    3594              : 
    3595              :         UG_LOG("vertex Infos Runde eins fertig " << std::endl);
    3596              : 
    3597              : #if 0
    3598              :         // Voraussetzung  FÜR StammiBene Aufrufung
    3599              :         // Stammi-Bene-Vorbereitung
    3600              :         for( VertexIterator iter = m_sel.begin<Vertex>(); iter != m_sel.end<Vertex>(); ++iter)
    3601              :         {
    3602              :                 Vertex* vrt = *iter;
    3603              : 
    3604              : //              std::vector<Volume*> & attVol = m_aaVrtInfoAssoVols[vrt];
    3605              : 
    3606              :                 auto & vrtxFracPrps = m_aaMarkVrtVFP[ vrt ];
    3607              : 
    3608              :                 VecAttachedFractFaceEdgeSudo vecAttFacEdgSudo = vrtxFracPrps.getAllAttachedFractElems();
    3609              : 
    3610              :                 auto & vecVolElmInfo = m_aaVolElmInfo[vrt];
    3611              : 
    3612              :                 // TODO FIXME eigentlich eine Dummheit, das auf zu teilen in ein VolElemInfo und ein VrtInfoAssoVols
    3613              :                 // denn die InfoAssoVols haben als Info nur die Volumen, die VolElmInfos haben die Volumen
    3614              :                 // und noch viel mehr Infos zu den Faces und den Edges....
    3615              :                 // mittelfristig die m_aaVrtInfoAssoVols abschaffen und alles auf die AttachedFullDimElemInfo
    3616              :                 // übertragen, dann geht der folgende Loop gleich über den Vektor darüber, bzw. gleichbedeutend
    3617              :                 // über m_aaVolElmInfo
    3618              : //              for( auto & vol : attVol )
    3619              :                 for( AttachedVolumeElemInfo & attVolElmInfo : vecVolElmInfo )
    3620              :                 {
    3621              : //                      AttachedVolumeElemInfo attVolElmInfo( vol );
    3622              :                         Volume * vol = attVolElmInfo.getFulldimElem();
    3623              : 
    3624              :                         // add those faces which are fracture faces
    3625              :                         for( auto & afes : vecAttFacEdgSudo )
    3626              :                         {
    3627              :                                 attVolElmInfo.addFractManifElem(afes, m_grid);
    3628              :                         }
    3629              : 
    3630              :                         // add those faces which are NOT fracture faces, assign them arbitraryly subdomain  -1
    3631              :                         // to indicate that they are not from the manifold, independent of their subdomain
    3632              : 
    3633              :                         // collect all volume faces which incorporate the vertex
    3634              : 
    3635              :                         std::vector<Face*> volFacesContainingVrtx;
    3636              : 
    3637              :                         for( IndexType iFac = 0; iFac < vol->num_faces(); iFac++ )
    3638              :                         {
    3639              :                                 Face * fac = m_grid.get_face(vol,iFac);
    3640              : 
    3641              :                                 if( FaceContains( fac, vrt ) )
    3642              :                                 {
    3643              :                                         volFacesContainingVrtx.push_back( fac );
    3644              :                                 }
    3645              :                         }
    3646              : 
    3647              :                         for( auto const & fac : volFacesContainingVrtx )
    3648              :                         {
    3649              :                                 // get the edges of the face connected to the vertex
    3650              : 
    3651              :                                 std::vector<Edge*> vecEdgesFaceVrtx;
    3652              : 
    3653              :                                 // need to be two edges always, check
    3654              : 
    3655              :                                 for( IndexType iEdge = 0; iEdge < fac->num_edges(); iEdge++ )
    3656              :                                 {
    3657              :                                         Edge * edg = m_grid.get_edge(fac,iEdge);
    3658              : 
    3659              :                                         if( EdgeContains(edg,vrt) )
    3660              :                                         {
    3661              :                                                 vecEdgesFaceVrtx.push_back(edg);
    3662              :                                         }
    3663              :                                 }
    3664              : 
    3665              :                                 if( vecEdgesFaceVrtx.size() != 2 )
    3666              :                                 {
    3667              :                                         UG_LOG("edge number Unsinn " << vecEdgesFaceVrtx.size() << std::endl);
    3668              :                                         UG_THROW("edge number Unsinn " << vecEdgesFaceVrtx.size() << std::endl);
    3669              :                                         return false;
    3670              :                                 }
    3671              : 
    3672              :                                 EdgePair edgesFaceVrtx( vecEdgesFaceVrtx[0], vecEdgesFaceVrtx[1] );
    3673              : 
    3674              :                                 // test the subdomain first, if from the subdomains of the cleft manifolds
    3675              : 
    3676              :                                 IndexType sudoThisFace = m_sh.get_subset_index(fac);
    3677              : 
    3678              :                                 std::vector<IndexType> const & sudoList = vrtxFracPrps.getSudoList();
    3679              : 
    3680              :                                 // test if sudo of face belongs to the fracture face subdom list
    3681              : 
    3682              :                                 bool belongsToFracFaceSudo = false;
    3683              : 
    3684              :                                 for( auto const & sudoFrac : sudoList )
    3685              :                                 {
    3686              :                                         if( sudoFrac == sudoThisFace )
    3687              :                                         {
    3688              :                                                 belongsToFracFaceSudo = true;
    3689              :                                                 break;
    3690              :                                         }
    3691              :                                 }
    3692              : 
    3693              : 
    3694              :                                 if( belongsToFracFaceSudo )
    3695              :                                 {
    3696              :                                         // if it belongs, construct it again and test if it already belongs to the fracture faces
    3697              :                                         // MUST be already part of the list, else major error appeared!
    3698              : 
    3699              :                                         AttachedFractFaceEdgeSudo afesTest( fac, edgesFaceVrtx, sudoThisFace );
    3700              : 
    3701              :                                         if( attVolElmInfo.addFractManifElem( afesTest, m_grid ) )
    3702              :                                         {
    3703              :                                                 UG_LOG("manifold element already contained!" << std::endl);
    3704              :                                                 UG_THROW("manifold element already contained!" << std::endl);
    3705              :                                                 return false;
    3706              :                                         }
    3707              : 
    3708              :                                         // nothing to do, already added before hoffentlich
    3709              : 
    3710              :                                 }
    3711              :                                 else
    3712              :                                 {
    3713              :                                         // zeitweilig fehlten alle Faces, die keine fractures sind
    3714              :                                         // die müssen noch irgendwie als nicht-fracture-faces auch dazu gefügt werden
    3715              :                                         // die sind in den attached volumes schon enthalten,
    3716              :                                         // Frage: wie prüfen, dass die gar keine fractures sind, die Infos sollten bekannt sein.....
    3717              :                                         // wichtig auch, dass nur die faces dazu kommen, die den Vertex enthalten!!!
    3718              :                                         // irgendwas von der Art "nonFractureFaceInfos" oder sowas dazu hängen, mit Info
    3719              :                                         // ob schon getouched oder noch nicht.....
    3720              : 
    3721              : 
    3722              :                                         // we construct the attached manifold, given that it is NOT a fracture manifold
    3723              : 
    3724              :                                         // notwendig auch, dass es eine Markierungsmöglichkeit gibt dafür, ob
    3725              :                                         // ein face bei der nächsten weiter inneren Runde quasi äussere Begrenzung sein muss
    3726              :                                         // gilt sowohl für fracture faces, die können das in erster Runde auch sein am Ende
    3727              :                                         // der Runde, sowie danach nur noch für nicht-fracture-faces
    3728              : 
    3729              :                                         AttachedGenerFaceEdgeSudo afesAdd( fac, edgesFaceVrtx );
    3730              : 
    3731              :                                         attVolElmInfo.addGenerManifElem( afesAdd, m_grid );
    3732              : 
    3733              :                                 }
    3734              : 
    3735              :                         }
    3736              : 
    3737              :                 }
    3738              :         }
    3739              : #endif
    3740              : 
    3741              :         UG_LOG("vertex Infos Runde eins fertig Volumen auch" << std::endl);
    3742              : 
    3743            0 :         return true;
    3744              : }
    3745              : 
    3746            0 : bool ArteExpandFracs3D::stasiAlgo( Vertex * const & oldVrt )
    3747              : {
    3748              : 
    3749            0 :         UG_LOG("Stasi start " << m_aaPos[oldVrt] << std::endl);
    3750              :         // TODO FIXME übernehmen von loop2EstablishNewVertices und establishNewVertices
    3751              :         // plus Boundary faces ähnlich Fracture
    3752              :         // am Ende die in Segment verbundenen offenen Fracture Faces verschwinden lassen
    3753              :         // Segmente erstellen Ziel hier, aber auch raus finden, ob es mehr als eines gibt
    3754              :         // oder ob es offen ist, wegen wahl
    3755              : 
    3756            0 :         vector3 posOldVrt = m_aaPos[oldVrt];
    3757              : 
    3758            0 :         UG_LOG("vertex at " << posOldVrt << std::endl);
    3759              : 
    3760            0 :         VecSegmentVolElmInfo & vecSegVolElmInfo = m_accsAttVecSegVolElmInfo[oldVrt];
    3761              : 
    3762              :         auto & vrtxFracPrps = m_aaMarkVrtVFP[ oldVrt ];
    3763              : 
    3764              :         bool isBndryVrtx = vrtxFracPrps.getIsBndFracVertex();
    3765              : 
    3766              :         UG_LOG("under construction Tetrahedra limited Stasi Algo" << std::endl);
    3767              : 
    3768              : //      VecVertFracTrip const & vecVertFracTrip = m_aaVrtInfoFraTri[oldVrt];
    3769              : 
    3770              :         VecAttachedVolumeElemInfo assoVolElemInfo;
    3771              : 
    3772              :         int bndryFacsFnd = 0;
    3773              : 
    3774            0 :         for( std::vector<Volume *>::iterator iterVol = m_grid.associated_volumes_begin(oldVrt);
    3775            0 :                                                                                  iterVol != m_grid.associated_volumes_end(oldVrt);
    3776              :                                                                                  iterVol++ )
    3777              :         {
    3778            0 :                 Volume * vol = *iterVol;
    3779              : 
    3780              :                 AttachedVolumeElemInfo avei(vol);
    3781              : 
    3782            0 :                 bndryFacsFnd += prepareStasi(oldVrt, avei);
    3783              : 
    3784            0 :                 assoVolElemInfo.push_back(avei);
    3785            0 :         }
    3786              : 
    3787            0 :         if( isBndryVrtx && bndryFacsFnd == 0 )
    3788              :         {
    3789              :                 UG_LOG("Boundary vertex with no boundary faces adjoint" << std::endl);
    3790            0 :                 UG_THROW("Boundary vertex with no boundary faces adjoint" << std::endl);
    3791              :                 return false;
    3792              :         }
    3793              : 
    3794              : 
    3795              : //      if( vrtxFracPrps.getIsBndFracVertex() )
    3796              : //      {
    3797              : //              for( AttachedVolumeElemInfo ave : assoVolElemInfo )
    3798              : //              {
    3799              : //                      UG_LOG("BONDVERT " << m_aaPos[oldVrt] << " -> " << ave.getVecBndryManifElem().size()  << std::endl);
    3800              : //                      if(  ave.getVecBndryManifElem().size() == 0 )
    3801              : //                      {
    3802              : //                              UG_THROW("VERLUST" << std::endl);
    3803              : //                      }
    3804              : //              }
    3805              : //      }
    3806              : 
    3807              :         // von copy und paste angepasst, die unsinnige Verdopplung von vecAttVolElemInfo und assoVolElemInfo
    3808              :         // vielleicht noch entfernen
    3809              :         VecAttachedVolumeElemInfo const & vecAttVolElemInfo = assoVolElemInfo; // m_aaVolElmInfo[oldVrt];
    3810              : 
    3811            0 :         VecAttachedVolumeElemInfo vecAttVolElemInfoCop = vecAttVolElemInfo; // echte KOPIE
    3812              : 
    3813              :         VecAttachedVolumeElemInfo reconstructedVecAttVolElmInf;
    3814              : 
    3815              :                 /*
    3816              :                  * While Schleifen aufbauen für den
    3817              :                  * Search the adjacent surface interatively - Algorithmus
    3818              :                  * (Stasi Algorithmus)
    3819              :                  *
    3820              :                  */
    3821              : 
    3822              :         IndexType d_segmenteErledigt = 0;
    3823              : 
    3824            0 :         while( vecAttVolElemInfoCop.size() != 0 )
    3825              :         {
    3826              :                 SegmentVolElmInfo segmentAVEI;
    3827              : 
    3828              :                 AttachedVolumeElemInfo & startVolInfoThisSegment = vecAttVolElemInfoCop[0];
    3829              : 
    3830              :                 startVolInfoThisSegment.markIt();
    3831              : 
    3832              :                 Volume * volSta = startVolInfoThisSegment.getFulldimElem();
    3833              : 
    3834              :                 vector3 center;
    3835              : 
    3836            0 :                 if( volSta != nullptr )
    3837            0 :                         center = CalculateCenter(volSta,m_aaPos);
    3838              : 
    3839              : //              UG_LOG("volume center " << center << std::endl );
    3840              : 
    3841              :                 int d_loopsDone = 0;
    3842              : 
    3843            0 :                 while( vecAttVolElemInfoCop.size() != 0 )
    3844              :                 {
    3845              :                         // count number of marked elements
    3846              :                         IndexType numMarkedElems = 0;
    3847              :                         IndexType markPoint = 0;
    3848              : 
    3849              : //                      IndexType lastMarkPt = 0;
    3850              :                         IndexType startIndexInner = 0;
    3851              : 
    3852            0 :                         for( AttachedVolumeElemInfo const & volElInfCop : vecAttVolElemInfoCop )
    3853              :                         {
    3854            0 :                                 if( volElInfCop.isMarked() )
    3855              :                                 {
    3856              :                                         Volume * vol = volElInfCop.getFulldimElem();
    3857              : //                                      m_sh.assign_subset(vol, m_sh.num_subsets());
    3858              : 
    3859            0 :                                         vector3 center = CalculateCenter(vol,m_aaPos);
    3860              : 
    3861              : //                                      UG_LOG("DAS ZENTRUM " << numMarkedElems << " -> " << center << std::endl);
    3862              : 
    3863              :                                         startIndexInner = markPoint;
    3864            0 :                                         numMarkedElems++;
    3865              : 
    3866              :                                 }
    3867              : 
    3868            0 :                                 markPoint++;
    3869              :                         }
    3870              : 
    3871              :                         UG_LOG("LOOPS DONE " << numMarkedElems << std::endl);
    3872              : 
    3873            0 :                         if( numMarkedElems == 0 )
    3874              :                                 break;
    3875              : 
    3876              : //                      int startIndexInner = -1;
    3877              : //
    3878              : //                      for( int i = 0; i < vecAttVolElemInfoCop.size(); i++ )
    3879              : //                      {
    3880              : //                              AttachedVolumeElemInfo vi = vecAttVolElemInfoCop[i];
    3881              : //
    3882              : //                              Volume * vo = vi.getFulldimElem();
    3883              : //
    3884              : //                              vector3 center = CalculateCenter(vo,m_aaPos);
    3885              : //
    3886              : //                              UG_LOG("DAS ZENTRUM ZAHL VOR " << i << " -> " <<  center << std::endl);
    3887              : //
    3888              : //                              if( vi.isMarked() )
    3889              : //                                      startIndexInner = i;
    3890              : //                      }
    3891              : //
    3892              : //                      if( startIndexInner < 0 )
    3893              : //                      {
    3894              : //                              UG_THROW("kein Anfang gefunden " << std::endl);
    3895              : //                      }
    3896              : //
    3897              : //#if 0
    3898              : //                      IndexType startIndexInner = markPoint - 1;
    3899              : //#endif
    3900            0 :                         AttachedVolumeElemInfo startVolInfoMarkLoop = vecAttVolElemInfoCop[startIndexInner];
    3901              : 
    3902              :                         Volume * stattVoll = startVolInfoMarkLoop.getFulldimElem();
    3903              : 
    3904            0 :                         vector3 centerX = CalculateCenter(stattVoll,m_aaPos);
    3905              : 
    3906            0 :                         UG_LOG("DAS ZENTRUM DANACH STASI" << startIndexInner << " -> " <<  centerX << std::endl);
    3907              : 
    3908              : //                      m_sh.assign_subset(stattVoll, m_sh.num_subsets());
    3909              : #if 0
    3910              :                         for( int i = 0; i < vecAttVolElemInfoCop.size(); i++ )
    3911              :                         {
    3912              :                                 AttachedVolumeElemInfo vi = vecAttVolElemInfoCop[i];
    3913              : 
    3914              :                                 Volume * vo = vi.getFulldimElem();
    3915              : 
    3916              :                                 vector3 center = CalculateCenter(vo,m_aaPos);
    3917              : 
    3918              :                                 UG_LOG("DAS ZENTRUM ZAHL " << i << " -> " <<  center << std::endl);
    3919              : 
    3920              :                         }
    3921              : #endif
    3922            0 :                         for( AttachedVolumeElemInfo const & possibleOrigVolInfo : vecAttVolElemInfo )
    3923              :                         {
    3924            0 :                                 if( possibleOrigVolInfo.hasSameFulldimElem( startVolInfoMarkLoop ) )
    3925              :                                 {
    3926            0 :                                         segmentAVEI.push_back(possibleOrigVolInfo);
    3927            0 :                                         reconstructedVecAttVolElmInf.push_back(possibleOrigVolInfo);
    3928              :                                         break;
    3929              :                                 }
    3930              :                         }
    3931              : 
    3932              :                         vecAttVolElemInfoCop.erase( vecAttVolElemInfoCop.begin() + startIndexInner );
    3933              : 
    3934              : //                      if( d_loopsDone == 1 )
    3935              : //                              return false;
    3936              : 
    3937            0 :                         for( VecAttachedVolumeElemInfo::iterator aveiIt = vecAttVolElemInfoCop.begin();
    3938            0 :                                                                                                          aveiIt < vecAttVolElemInfoCop.end();
    3939              :                                                                                                          aveiIt++
    3940              :                         )
    3941              :                         {
    3942              :                                 AttachedVolumeElemInfo & possibleNeighbour = *aveiIt;
    3943              : 
    3944            0 :                                 if( possibleNeighbour.hasSameFulldimElem( startVolInfoMarkLoop ) )
    3945              :                                 {
    3946            0 :                                         continue;
    3947              :                                 }
    3948              :                                 else
    3949              :                                 {
    3950            0 :                                         bool neighbourFound = possibleNeighbour.testFullDimElmNeighbour( startVolInfoMarkLoop );
    3951              : 
    3952              :                                         if( neighbourFound )
    3953              :                                         {
    3954              :                                                 Volume * vol = possibleNeighbour.getFulldimElem();
    3955              : 
    3956              : //                                              m_sh.assign_subset(vol, m_sh.num_subsets());
    3957              : 
    3958              :                                         }
    3959              :                                 }
    3960              :                         }
    3961              : 
    3962              : 
    3963              :                         d_loopsDone++;
    3964              : 
    3965              : 
    3966            0 :                 }
    3967              : 
    3968            0 :                 vecSegVolElmInfo.push_back(segmentAVEI);
    3969              : 
    3970              : //              d_segmenteErledigt++;
    3971              : //
    3972              : //              if( d_segmenteErledigt == 1 )
    3973              : //              return false;
    3974            0 :         }
    3975              : 
    3976            0 :         if( reconstructedVecAttVolElmInf.size() != vecAttVolElemInfo.size() )
    3977              :         {
    3978              :                 UG_LOG("Rekonstruktion schief gegangen " << std::endl);
    3979            0 :                 UG_THROW("Rekonstruktion schief gegangen " << std::endl);
    3980              :                 return false;
    3981              :         }
    3982              : 
    3983              : // for debug purposes
    3984              : 
    3985              :         constexpr bool d_assignSudos2Segments = false;
    3986              : 
    3987              :         if( d_assignSudos2Segments )
    3988              :         {
    3989              :                 if( vecSegVolElmInfo.size() > 1 )
    3990              :                 {
    3991              :                         for( SegmentVolElmInfo const & svei : vecSegVolElmInfo )
    3992              :                         {
    3993              :                                 // TODO FIXME das hier wieder entfernen, die Subdomain Zuweisung, nur für debug Zwecke
    3994              :                                 IndexType sudoMax = m_sh.num_subsets();
    3995              : 
    3996              :                                 for( AttachedVolumeElemInfo const & vei : svei )
    3997              :                                 {
    3998              :                                         Volume * vol = vei.getFulldimElem();
    3999              : 
    4000              :                                         m_sh.assign_subset( vol, sudoMax );
    4001              :                                 }
    4002              :                         }
    4003              :                 }
    4004              :         }
    4005              : 
    4006            0 :         UG_LOG("Stasi END " << m_aaPos[oldVrt] << std::endl);
    4007              : 
    4008              :         return true;
    4009            0 : }
    4010              : 
    4011              : #if 0
    4012              : // Deprecated due to Stasi Algo
    4013              : // herausfinden für Sudo der frac, ob bezüglich dieser sudo die faces geschlossen sind, oder ob ein Fracture End vorliegt
    4014              : bool ArteExpandFracs3D::isVrtxSurroundedByFracFaces( Vertex * const & vrt, VertxFracPropts & vrtxFracPrps )
    4015              : //, VecPairSudoBool & sudoSurrounded )
    4016              : {
    4017              :         // TODO FIXME wenn an Boundary, dann auch auf closed open unterscheiden - sowohl wenn nur edge an
    4018              :         // boundary, aber auch wenn ein ganzes face dort, noch unklar, was das bedeutet
    4019              : 
    4020              :         // ganz ähnlich wie im 2D Fall, Loopen, im Kreis drehen, kucken, ob wir vom Anfang ans Ende kommen,
    4021              :         // und ob das Ende der edges wieder der Anfang der edges ist, da wir uns auf faces drehen
    4022              : 
    4023              :         // case boundary: figure out if the vertex is surrounded by frac faces of which two end in
    4024              :         // boundary edges, similar the case when the boundary face has itself two
    4025              :         // boundary edges, where the vertex is connected to both of them, then it is easy
    4026              : 
    4027              : 
    4028              :         VecAttachedFractFaceEdgeSudo vafes = vrtxFracPrps.getAllAttachedFractElems();
    4029              : 
    4030              :         std::vector<IndexType> sudoList = vrtxFracPrps.getSudoList();
    4031              : 
    4032              : //      for( auto const & sudo : sudoList )
    4033              : //      {
    4034              : //              std::vector<Face*> tmpFaces;
    4035              : //
    4036              : //              CollectFaces( tmpFace, m_grid, vrt );
    4037              : //
    4038              : //      }
    4039              : 
    4040              :         // first compare sudo list, if equal
    4041              : 
    4042              :         std::vector<IndexType> sudosTestList;
    4043              : 
    4044              :         std::vector<bool> sudoFound( sudoList.size(), false );
    4045              : 
    4046              :         UG_LOG("sudo list size " << sudoList.size() << std::endl );
    4047              : 
    4048              :         UG_LOG("vafes list size VA " << vafes.size() << std::endl );
    4049              : 
    4050              : 
    4051              :         for( auto const & af : vafes )
    4052              :         {
    4053              :                 bool found = false;
    4054              : 
    4055              :                 IndexType sudo = af.getSudo();
    4056              : 
    4057              :                 UG_LOG("sudo af " << sudo << std::endl);
    4058              : 
    4059              :                 for( IndexType i = 0; i < sudoList.size(); i++ )
    4060              :                 {
    4061              :                         UG_LOG("sudo list dusso is " << sudoList[i] << std::endl);
    4062              : 
    4063              :                         if( sudo == sudoList[i] )
    4064              :                         {
    4065              :                                 sudoFound[i] = true;
    4066              :                                 found = true;
    4067              :                         }
    4068              :                 }
    4069              : 
    4070              : 
    4071              :                 if( ! found )
    4072              :                         UG_THROW("sudo nicht gefunden muss aber da sein " << std::endl);
    4073              :         }
    4074              : 
    4075              :         UG_LOG("alles gefunden " << std::endl);
    4076              : 
    4077              : 
    4078              :         for( auto const & sf: sudoFound )
    4079              :         {
    4080              :                 if( sf == false )
    4081              :                 {
    4082              :                         UG_LOG("Falsch" << std::endl);
    4083              :                         UG_THROW("sudo not found but must be there " << std::endl);
    4084              :                 }
    4085              :         }
    4086              : 
    4087              :         UG_LOG("alles gefunden Test " << std::endl);
    4088              : 
    4089              : 
    4090              :         // sort faces with respect to subdomain - macht das wirklich Sinn, wie umständlich das gemacht wird jetzt?
    4091              : 
    4092              :         // if we arrive here, all sudos found, the entire circle closing can start
    4093              : 
    4094              :         VecPairSudoBool sudoSurrounded;
    4095              : 
    4096              :         for( auto const & sudo : sudoList )
    4097              :         {
    4098              :                 VecAttachedFractFaceEdgeSudo vecAttFacSudo;
    4099              : 
    4100              :                 for( auto const & attFac : vafes )
    4101              :                 {
    4102              :                         if( sudo == attFac.getSudo() )
    4103              :                         {
    4104              :                                 UG_LOG("die sudo gefunden " << sudo << std::endl);
    4105              :                                 vecAttFacSudo.push_back(attFac);
    4106              :                         }
    4107              :                 }
    4108              : 
    4109              :                 VecAttachedFractFaceEdgeSudo vecAttFacSudoSort;
    4110              : 
    4111              : 
    4112              : 
    4113              :                 bool isClosed = false;
    4114              : 
    4115              :                 bool isBndVrtx = IsBoundaryVertex3D(m_grid,vrt);
    4116              : 
    4117              :                 if( ! isBndVrtx )
    4118              :                 {
    4119              :                         UG_LOG("No boundary vertex test closed " << m_aaPos[vrt] << std::endl);
    4120              : 
    4121              :                         if( vecAttFacSudo.size() == 1 )
    4122              :                         {
    4123              :                                 // no need for further investigations for inner faces
    4124              :                                 isClosed = false;
    4125              :                                 vecAttFacSudoSort = vecAttFacSudo;
    4126              :                         }
    4127              :                         else
    4128              :                         {
    4129              :                                 isClosed = sortElemCircleIsClosed( vecAttFacSudo, vecAttFacSudoSort );
    4130              :                         }
    4131              : 
    4132              :                 }
    4133              :                 else // different treatment boundary vertex
    4134              :                 {
    4135              :                         // figure out start face with a boundary edge, and figure out an eventual additional boundary edge
    4136              :                         // if only one face, then check if two attached boundary edges, then true, else false
    4137              : 
    4138              :                         if( vecAttFacSudo.size() == 1 )
    4139              :                         {
    4140              :                                 AttachedFractFaceEdgeSudo & singleEntry = vecAttFacSudo[0];
    4141              : 
    4142              :                                 EdgePair faceEdgs = singleEntry.getPairLowElm();
    4143              : 
    4144              :                                 if( IsBoundaryEdge3D(m_grid, faceEdgs.first) && IsBoundaryEdge3D(m_grid, faceEdgs.second ) )
    4145              :                                         isClosed = true;
    4146              : 
    4147              :                                 // very simple
    4148              :                                 vecAttFacSudoSort = vecAttFacSudo;
    4149              : 
    4150              :                         }
    4151              :                         else
    4152              :                         {
    4153              :                                 // figure out a begin face with a boundary edge and figure out another face with a boundary edge
    4154              : 
    4155              :                                 Edge * beginEdge = nullptr;
    4156              :                                 Edge * endEdge = nullptr;
    4157              : 
    4158              :                                 IndexType startFaceIndx = 0;
    4159              :                                 IndexType endFaceIndx = 0;
    4160              : 
    4161              :                                 for( auto const & afs : vecAttFacSudo )
    4162              :                                 {
    4163              :                                         Face * fac = afs.getManifElm();
    4164              : 
    4165              :                                         EdgePair edgs = afs.getPairLowElm();
    4166              : 
    4167              :                                         Edge * edgOne = edgs.first;
    4168              :                                         Edge * edgTwo = edgs.second;
    4169              : 
    4170              :                                         if( beginEdge == nullptr )
    4171              :                                         {
    4172              :                                                 if( IsBoundaryEdge3D(m_grid, edgOne) )
    4173              :                                                 {
    4174              :                                                         beginEdge = edgTwo;
    4175              :                                                 }
    4176              :                                                 else if( IsBoundaryEdge3D(m_grid, edgTwo) )
    4177              :                                                 {
    4178              :                                                         beginEdge = edgOne;
    4179              :                                                 }
    4180              :                                                 else
    4181              :                                                 {
    4182              :                                                         startFaceIndx++;
    4183              :                                                 }
    4184              :                                         }
    4185              :                                         else
    4186              :                                         {
    4187              :                                                 if( IsBoundaryEdge3D(m_grid, edgOne) )
    4188              :                                                 {
    4189              :                                                         endEdge = edgOne;
    4190              :                                                 }
    4191              :                                                 else if( IsBoundaryEdge3D(m_grid, edgTwo) )
    4192              :                                                 {
    4193              :                                                         endEdge = edgTwo;
    4194              :                                                 }
    4195              :                                         }
    4196              : 
    4197              :                                         if( endEdge != nullptr )
    4198              :                                                 break;
    4199              : 
    4200              :                                         endFaceIndx++;
    4201              :                                 }
    4202              : 
    4203              :                                 if( beginEdge == nullptr && endFaceIndx == vecAttFacSudo.size() )
    4204              : //                                      || beginEdge == nullptr || endEdge == nullptr )
    4205              :                                 {
    4206              :                                         UG_LOG("keine boundary edges" << std::endl);
    4207              : 
    4208              :                                         startFaceIndx = -1;
    4209              : 
    4210              :                                         if( endEdge != nullptr )
    4211              :                                                 UG_THROW("Ende nicht null, Anfang null " << std::endl);
    4212              :                                 }
    4213              : 
    4214              :                                 UG_LOG("Boundary vertex test closed " << m_aaPos[vrt] << std::endl);
    4215              : 
    4216              : //                              int d_num = 0;
    4217              : //                              for( auto const & afs : vecAttFacSudo )
    4218              : //                              {
    4219              : //                                      d_num++;
    4220              : //                                      Face * fac = afs.getManifElm();
    4221              : //                                      m_sh.assign_subset(fac, m_sh.num_subsets());
    4222              : //                              }
    4223              : //                              UG_LOG("number of surr faces " << d_num << std::endl );
    4224              : 
    4225              : //                              m_sh.assign_subset(beginEdge,m_sh.num_subsets());
    4226              : //                              m_sh.assign_subset(endEdge,m_sh.num_subsets());
    4227              : //                              m_sh.assign_subset(vecAttFacSudo[startFaceIndx].getManifElm(),m_sh.num_subsets());
    4228              : 
    4229              :                                 isClosed = sortElemCircleIsClosed( vecAttFacSudo, vecAttFacSudoSort, startFaceIndx, beginEdge, endEdge );
    4230              : 
    4231              :                         }
    4232              :                 }
    4233              : 
    4234              :                 UG_LOG("-------------------------------" << std::endl);
    4235              :                 UG_LOG("is closed " << isClosed << " at " << m_aaPos[vrt] << std::endl);
    4236              :                 UG_LOG("-------------------------------" << std::endl);
    4237              : 
    4238              : //              if( isClosed )
    4239              : //              {
    4240              : //                      m_sh.assign_subset(vrt,3);
    4241              : //              }
    4242              : //              else
    4243              : //              {
    4244              : //                      m_sh.assign_subset(vrt,4);
    4245              : //              }
    4246              : 
    4247              :                 if( vecAttFacSudo.size() != vecAttFacSudoSort.size() )
    4248              :                 {
    4249              : //                      return false;
    4250              : 
    4251              :                         UG_THROW("Die Sortierung ist komplett schief gegangen " << std::endl);
    4252              :                 }
    4253              : 
    4254              :                 // DEBUG Zeug, später entfernen!!!!!!
    4255              : //              for( auto const & afss : vecAttFacSudoSort )
    4256              : //              {
    4257              : //                      Face * fac = afss.getManifElm();
    4258              : //
    4259              : //                      m_sh.assign_subset(fac, m_sh.num_subsets());
    4260              : //              }
    4261              : 
    4262              :                 PairSudoBool ic( sudo, isClosed );
    4263              : 
    4264              :                 sudoSurrounded.push_back( ic );
    4265              : 
    4266              :         }
    4267              : 
    4268              :         vrtxFracPrps.setInfoAllFractureSudosIfClosed(sudoSurrounded);
    4269              : 
    4270              :         bool allClosed = true;
    4271              : 
    4272              :         for( auto const & ic : sudoSurrounded )
    4273              :         {
    4274              :                 if( ! ic.second )
    4275              :                         allClosed = false;
    4276              :         }
    4277              : 
    4278              :         return allClosed;
    4279              : }
    4280              : 
    4281              : bool ArteExpandFracs3D::sortElemCircleIsClosed( VecAttachedFractFaceEdgeSudo const & vecAttFac,
    4282              :                                                                                                 VecAttachedFractFaceEdgeSudo & vecSortedFac,
    4283              :                                                                                                 int startFacIndexUser,
    4284              : //                                                                                              int endFacIndexUser,
    4285              : //                                                                                              IndexType startEdgeIndexUser,
    4286              : //                                                                                              IndexType endEdgeIndexUser
    4287              : //                                                                                              Face * const & startFacUser,
    4288              : //                                                                                              Face * const & endFacUser,
    4289              :                                                                                                 Edge * const & startEdgUser,
    4290              :                                                                                                 Edge * const & endEdgUser
    4291              :                                                                                                 )
    4292              : {
    4293              : 
    4294              :         UG_LOG("Schliesstest" << std::endl);
    4295              : 
    4296              :         IndexType originalSize = vecAttFac.size();
    4297              : 
    4298              :         if( originalSize == 0 )
    4299              :         {
    4300              :                 UG_THROW("zu klein zum sortieren " << std::endl);
    4301              :                 return false;
    4302              :         }
    4303              :         else if ( originalSize == 1 )
    4304              :         {
    4305              :                 UG_THROW("should not happen size 1, should have been mentioned before " << std::endl);
    4306              :         }
    4307              : 
    4308              :         UG_LOG("Kopieren zwecks sortieren " << std::endl);
    4309              : 
    4310              :         for( auto const & af : vecAttFac )
    4311              :         {
    4312              :                 UG_LOG("die sudos innen sind " << af.getSudo() << std::endl);
    4313              :         }
    4314              : 
    4315              :         VecAttachedFractFaceEdgeSudo copyVecAttFac = vecAttFac;
    4316              : 
    4317              :         for( auto const & af : copyVecAttFac )
    4318              :         {
    4319              :                 UG_LOG("die sudos kopiert sind " << af.getSudo() << std::endl);
    4320              :         }
    4321              : 
    4322              :         IndexType beginIndx = 0;
    4323              : 
    4324              :         UG_LOG("begin Index " << beginIndx << std::endl);
    4325              : 
    4326              :         bool simpleConnectionTest = false;
    4327              : 
    4328              :         Edge * startEdgeForced = nullptr;
    4329              : 
    4330              :         if( startFacIndexUser >= 0 )
    4331              :         {
    4332              :                 UG_LOG("Veränderung " << startFacIndexUser << std::endl);
    4333              :                 beginIndx = startFacIndexUser;
    4334              :                 simpleConnectionTest = true; // user hopefully did it
    4335              :         }
    4336              :         else
    4337              :         {
    4338              :                 // we need to ensure to start at a fracture which is not in between, in case that circle not closed
    4339              :                 // so ensure that all fracture faces have a fracture face at both edges as neighbour,
    4340              :                 // in principle this is already sufficient to answer the question which we want to know
    4341              :                 // all the rest here is useless playing in principle
    4342              : 
    4343              :                 bool broken = false;
    4344              : 
    4345              :                 for( IndexType i = 0; i < vecAttFac.size(); i++ )
    4346              :                 {
    4347              :                         IndexType firstSideConnected = 0;
    4348              :                         IndexType secondSideConnected = 0;
    4349              : 
    4350              :                         AttachedFractFaceEdgeSudo afBase = vecAttFac[i];
    4351              : 
    4352              :                         Face * faceBase = afBase.getManifElm();
    4353              :                         EdgePair edgPairBase = afBase.getPairLowElm();
    4354              : 
    4355              :                         Edge * edgeBaseOne = edgPairBase.first;
    4356              :                         Edge * edgeBaseTwo = edgPairBase.second;
    4357              : 
    4358              :                         for( IndexType j = 0; j < vecAttFac.size(); j++ )
    4359              :                         {
    4360              :                                 if( i != j )
    4361              :                                 {
    4362              :                                         AttachedFractFaceEdgeSudo afCompr = vecAttFac[j];
    4363              : 
    4364              :                                         Face * faceCompr = afCompr.getManifElm();
    4365              :                                         EdgePair edgPairCompr = afCompr.getPairLowElm();
    4366              : 
    4367              :                                         Edge * edgeComprOne = edgPairCompr.first;
    4368              :                                         Edge * edgeComprTwo = edgPairCompr.second;
    4369              : 
    4370              :                                         if( edgeComprOne == edgeBaseOne || edgeComprTwo == edgeBaseOne )
    4371              :                                                 firstSideConnected++;
    4372              : 
    4373              :                                         if( edgeComprOne == edgeBaseTwo || edgeComprTwo == edgeBaseTwo )
    4374              :                                                 secondSideConnected++;
    4375              :                                 }
    4376              : 
    4377              :                         }
    4378              : 
    4379              :                         if( vecAttFac.size() > 2 && ( firstSideConnected > 1 || secondSideConnected > 1 ) )
    4380              :                         {
    4381              :                                 UG_THROW("zu oft verbunden " << std::endl );
    4382              :                         }
    4383              :                         else if( vecAttFac.size() == 2 && ( firstSideConnected > 2 || secondSideConnected > 2 ) )
    4384              :                         {
    4385              :                                 UG_THROW("zu oft verbunden " << std::endl );
    4386              :                         }
    4387              :                         else if( firstSideConnected == 0 )
    4388              :                         {
    4389              :                                 // face is open into one direction, already clear that not closed!!
    4390              : 
    4391              :                                 beginIndx = i;
    4392              :                                 simpleConnectionTest = false;
    4393              :                                 startEdgeForced = edgeBaseTwo;
    4394              :                                 UG_LOG("forcieren 1 " << std::endl);
    4395              :                                 broken = true;
    4396              :                                 break;
    4397              :                         }
    4398              :                         else if( secondSideConnected == 0 )
    4399              :                         {
    4400              :                                 // face is open into one direction, already clear that not closed!!
    4401              : 
    4402              :                                 beginIndx = i;
    4403              :                                 simpleConnectionTest = false;
    4404              :                                 startEdgeForced = edgeBaseOne;
    4405              :                                 UG_LOG("forcieren 2 " << std::endl);
    4406              :                                 broken = true;
    4407              :                                 break;
    4408              :                         }
    4409              :                         else if( firstSideConnected == 1 && secondSideConnected == 1 )
    4410              :                         {
    4411              :                                 simpleConnectionTest = true; // as long as a look
    4412              :                         }
    4413              :                         else
    4414              :                         {
    4415              :                                 UG_THROW("komischer Verbindungsfall " << std::endl);
    4416              :                         }
    4417              : 
    4418              :                         if( broken )
    4419              :                                 break;
    4420              : 
    4421              :                 }
    4422              :         }
    4423              : 
    4424              :         UG_LOG("begin Index X " << beginIndx << std::endl);
    4425              : 
    4426              : 
    4427              : //      AttachedFractFaceEdgeSudo initialAFES = *(copyAttFac.begin());
    4428              :         AttachedFractFaceEdgeSudo initialAFES = copyVecAttFac[beginIndx];
    4429              : 
    4430              :         IndexType sudo = initialAFES.getSudo();
    4431              : 
    4432              :         UG_LOG("sudo " << beginIndx << " ist " << sudo << std::endl);
    4433              : 
    4434              :         Face * beginFacLoop = initialAFES.getManifElm();
    4435              : 
    4436              :         // TODO FIXME wird das irgendwo verwendet? wieso nicht?
    4437              : //      Face * endFacLoop = nullptr;
    4438              : 
    4439              : //      if( endFacIndexUser != -1 )
    4440              : //      {
    4441              : //              endFacLoop = copyVecAttFac[endFacIndexUser].getManifElm();
    4442              : //      }
    4443              : 
    4444              :         EdgePair beginEdges = initialAFES.getPairLowElm();
    4445              : 
    4446              :         Edge * beginEdgeLoop = beginEdges.second;
    4447              :         Edge * targetedEndEdgeLoop = beginEdges.first; // should be closed! should end at same edge as it begins!
    4448              : 
    4449              : //
    4450              : //      return true;
    4451              : 
    4452              : //      if( startEdgeIndexUser != -1 )
    4453              : //      {
    4454              : //              beginEdgeLoop =
    4455              : //      }
    4456              : 
    4457              : //      if( startFacUser != nullptr )
    4458              : //      {
    4459              : //              beginFacLoop = startFacUser;
    4460              : //
    4461              : //      }
    4462              : //
    4463              : 
    4464              : //      if( ! FaceContains(beginFacLoop,beginEdgeLoop->vertex(0)) )
    4465              : //              UG_THROW("Sortierung Gesicht hat nicht die gewünschte Ecke " << std::endl);
    4466              : //
    4467              : //      if( endFacUser != nullptr )
    4468              : //      {
    4469              : //              endFacLoop = endFacUser;
    4470              : //      }
    4471              : //
    4472              : 
    4473              :         if( startEdgUser != nullptr )
    4474              :         {
    4475              :                 beginEdgeLoop = startEdgUser;
    4476              : 
    4477              :                 // check if part of the begin face!
    4478              : 
    4479              :                 if( ! FaceContains( beginFacLoop, beginEdgeLoop ) )
    4480              :                         UG_THROW("Anfangsgesicht hat keine Anfangsecke " << std::endl);
    4481              : 
    4482              :         }
    4483              : 
    4484              :         if( startEdgeForced != nullptr )
    4485              :         {
    4486              :                 beginEdgeLoop = startEdgeForced;
    4487              : 
    4488              :                 // check if part of the begin face!
    4489              : 
    4490              :                 if( ! FaceContains( beginFacLoop, beginEdgeLoop ) )
    4491              :                         UG_THROW("Anfangsgesicht hat keine Anfangsecke forced " << std::endl);
    4492              : 
    4493              : //              m_sh.assign_subset(startEdgeForced, m_sh.num_subsets());
    4494              :                 UG_LOG("forciert " << std::endl);
    4495              : 
    4496              : //              return false;
    4497              : 
    4498              :         }
    4499              : 
    4500              : 
    4501              :         if( endEdgUser != nullptr )
    4502              :         {
    4503              :                 // check if part of end face at end of loop somehow
    4504              :                 targetedEndEdgeLoop = endEdgUser;
    4505              : 
    4506              :                 if( startEdgeForced != nullptr )
    4507              :                         UG_THROW("das muss schief gehen, Chaos " << std::endl);
    4508              : 
    4509              : //              if( endFacLoop != nullptr )
    4510              : //              {
    4511              : //                      if( ! FaceContains( endFacLoop, targetedEndEdgeLoop ) )
    4512              : //                              UG_THROW("Endgesicht hat keine Endecke " << std::endl);
    4513              : //              }
    4514              :         }
    4515              : //
    4516              : 
    4517              :         // DEBUG
    4518              : //      m_sh.assign_subset(beginFacLoop, m_sh.num_subsets());
    4519              : //      m_sh.assign_subset(beginEdgeLoop, m_sh.num_subsets());
    4520              : //      m_sh.assign_subset(targetedEndEdgeLoop, m_sh.num_subsets());
    4521              : 
    4522              : 
    4523              :         // Du musst sortieren. Du musst einen Zeitplan machen. Das kann man lernen. Du kannst das selber machen.
    4524              : 
    4525              :         IndexType countedCrossedFaces = 1;
    4526              : 
    4527              :         vecSortedFac.push_back( initialAFES );
    4528              : 
    4529              :         copyVecAttFac.erase( copyVecAttFac.begin() + beginIndx );
    4530              : 
    4531              : //      Face * face2Append = beginFacLoop;
    4532              :         Edge * startEdge2Append = beginEdgeLoop;
    4533              : 
    4534              : //      m_sh.assign_subset(startEdge2Append,m_sh.num_subsets());
    4535              : 
    4536              :         UG_LOG("while loop anfangen " << std::endl);
    4537              : 
    4538              :         IndexType d_whi = 0;
    4539              : 
    4540              :         while( copyVecAttFac.size() != 0 )
    4541              :         {
    4542              : 
    4543              :                 UG_LOG("in while loop " << d_whi << std::endl);
    4544              :                 d_whi++;
    4545              : 
    4546              :                 IndexType foundCommEdg = 0;
    4547              : 
    4548              :                 Edge * nextEdge = nullptr;
    4549              : 
    4550              : //              for( auto const & caf : copyVecAttFac )
    4551              :                 for( VecAttachedFractFaceEdgeSudo::iterator itAttFES  = copyVecAttFac.begin();
    4552              :                                                                                            itAttFES != copyVecAttFac.end();
    4553              :                                                                                            itAttFES++
    4554              :                 )
    4555              :                 {
    4556              :                         AttachedFractFaceEdgeSudo caf = *itAttFES;
    4557              : 
    4558              :                         Face * d_Fac = caf.getManifElm();
    4559              : 
    4560              : //                      m_sh.assign_subset(d_Fac,m_sh.num_subsets());
    4561              : 
    4562              :                         EdgePair edgPr = caf.getPairLowElm();
    4563              : 
    4564              :                         Edge * edgOne = edgPr.first;
    4565              :                         Edge * edgTwo = edgPr.second;
    4566              : 
    4567              : //                      m_sh.assign_subset(edgOne,m_sh.num_subsets());
    4568              : //                      m_sh.assign_subset(edgTwo,m_sh.num_subsets());
    4569              : 
    4570              : //                      return true;
    4571              : 
    4572              :                         IndexType hasEdge = 0;
    4573              : 
    4574              :                         Edge * overNextEdge = nullptr;
    4575              : 
    4576              :                         if( edgOne == startEdge2Append )
    4577              :                         {
    4578              :                                 nextEdge = edgOne;
    4579              :                                 overNextEdge = edgTwo;
    4580              :                                 hasEdge++;
    4581              :                         }
    4582              : 
    4583              :                         if( edgTwo == startEdge2Append )
    4584              :                         {
    4585              :                                 nextEdge = edgTwo;
    4586              :                                 overNextEdge = edgOne;
    4587              :                                 hasEdge++;
    4588              :                         }
    4589              : 
    4590              :                         if( hasEdge > 1 )
    4591              :                                 UG_THROW("zu viele Ecken und Kanten " << std::endl);
    4592              : 
    4593              :                         if( hasEdge == 1 )
    4594              :                         {
    4595              :                                 Face * fac2App = caf.getManifElm();
    4596              : //                              m_sh.assign_subset(fac2App,m_sh.num_subsets());
    4597              :                                 EdgePair edgesNextFace( edgOne, edgTwo );
    4598              :                                 AttachedFractFaceEdgeSudo nextAttFES( fac2App, edgesNextFace, sudo );
    4599              : 
    4600              :                                 vecSortedFac.push_back(nextAttFES);
    4601              : 
    4602              :                                 copyVecAttFac.erase(itAttFES);
    4603              :                                 foundCommEdg++;
    4604              :                                 startEdge2Append = overNextEdge;
    4605              : 
    4606              :                                 break;
    4607              :                         }
    4608              : 
    4609              : 
    4610              :                 }
    4611              : 
    4612              :                 if( foundCommEdg > 1 )
    4613              :                         UG_THROW("Kein Anschluss unter dieser Nummer " << std::endl);
    4614              : 
    4615              :                 if( foundCommEdg == 0 )
    4616              :                 {
    4617              :                         UG_LOG("Kreislauf nicht geschlossen " << std::endl);
    4618              : 
    4619              :                         if( nextEdge != nullptr )
    4620              :                                 UG_THROW("nicht konsistent, null und null " << std::endl);
    4621              : 
    4622              :                         break;
    4623              :                 }
    4624              : 
    4625              :                 if( nextEdge == nullptr )
    4626              :                 {
    4627              :                         if( foundCommEdg != 0 )
    4628              :                                 UG_THROW("nicht konsistent, null und null v2 " << foundCommEdg << " -> " << nextEdge << std::endl);
    4629              : 
    4630              :         //                      return false;
    4631              :                 }
    4632              : 
    4633              :         }
    4634              : 
    4635              :         if( originalSize != vecSortedFac.size() )
    4636              :         {
    4637              :                 UG_THROW("Sortierung hat nicht funktioniert " << std::endl);
    4638              :                 return false;
    4639              :         }
    4640              : 
    4641              :         if( startEdge2Append != targetedEndEdgeLoop )
    4642              :         {
    4643              :                 if( simpleConnectionTest )
    4644              :                         UG_THROW("obwohl offen oder vorgegeben trotzdem Ziel nicht erreicht?" << std::endl);
    4645              : 
    4646              :                 UG_LOG("Ende nicht erreicht, Kreis nicht geschlossen, innerer Rand vermutlich" << std::endl);
    4647              :                 return false;
    4648              :         }
    4649              : 
    4650              : 
    4651              :         UG_LOG("Kreislauf Faces 3D Test ob Knoten umrandet geschlossen " << std::endl);
    4652              : 
    4653              :         return true;
    4654              : }
    4655              : 
    4656              : #endif
    4657              : 
    4658            0 : bool ArteExpandFracs3D::assignOrigFracInfos()
    4659              : {
    4660              :         m_originalFractureFaces.clear();
    4661              : 
    4662            0 :         for( FaceIterator iter = m_sel.begin<Face>(); iter != m_sel.end<Face>(); ++iter)
    4663              :         {
    4664            0 :                 if( m_aaMarkFaceIsFracB[*iter] == true )
    4665            0 :                         m_originalFractureFaces.push_back(*iter);
    4666              :         }
    4667              : 
    4668            0 :         m_fracInfosBySubset = std::vector<FractureInfo>( m_sh.num_subsets(), FractureInfo(-1, -1, 0) );
    4669              : 
    4670            0 :         for(size_t i = 0; i < m_fracInfos.size(); ++i)
    4671              :         {
    4672            0 :                 if( m_fracInfos[i].subsetIndex >= m_sh.num_subsets())
    4673              :                 {
    4674            0 :                         throw(UGError("Bad subsetIndex in given fracInfos."));
    4675              :                 }
    4676              : 
    4677            0 :                 m_fracInfosBySubset[ m_fracInfos[i].subsetIndex ] = m_fracInfos[i];
    4678              :         }
    4679              : 
    4680              : //      disable selection inheritance to avoid infinite recursion.
    4681            0 :         m_sel.enable_selection_inheritance(false);
    4682              : 
    4683            0 :         return true;
    4684              : }
    4685              : 
    4686            0 : bool ArteExpandFracs3D::establishNewVrtBase()
    4687              : {
    4688              :         //      iterate over all surrounding volumes to enable shifted vertices, this loop taken from SR but shortened
    4689              : 
    4690            0 :         for( VolumeIterator iterSurrVol = m_sel.volumes_begin(); iterSurrVol != m_sel.volumes_end(); ++ iterSurrVol )
    4691              :         {
    4692              :                 Volume* sv = *iterSurrVol;
    4693              : 
    4694              :                 std::vector<Vertex*> & newVrts = m_aaVrtVecVol[sv];
    4695            0 :                 newVrts.resize(sv->num_vertices());
    4696              : 
    4697            0 :                 for(size_t iVrt = 0; iVrt < sv->num_vertices(); ++ iVrt )
    4698              :                 {
    4699            0 :                         newVrts[iVrt] = nullptr;
    4700              :                 }
    4701              : 
    4702              :                 // erstmal so tun, als ob keine neuen Vertizes erzeugt werden an den alten Vertizes
    4703              : 
    4704              :         }
    4705              : 
    4706            0 :         return true;
    4707              : }
    4708              : 
    4709              : #if 0
    4710              : // Analogon zu VertrexFractureInfo in 2D, wo jeder Vertex eine Liste bekommt, wo alle die ihm angehängten
    4711              : // Ecken, Faces und Volumen gespeichert werden; dazu die Normalen, und vielleicht noch weitere Infos
    4712              : bool ArteExpandFracs3D::generateVertexInfos()
    4713              : {
    4714              :         UG_LOG("Starte Generierung" << std::endl);
    4715              : 
    4716              :         // TODO FIXME das wird benötigt
    4717              : 
    4718              :         // sowas von der Art als attachement bei den attachments, und dann mit Leben füllen für jeden Vertex
    4719              :         // in dieser Funktion;
    4720              :         // vielleicht braucht es auch Edge Infos, oder nur Edge Infos?
    4721              : //      VecVertFracTrip vertexNoInfo;
    4722              : //      using AttVecVertFracTrip = Attachment<VecVertFracTrip>;
    4723              : //      AttVecVertFracTrip aAdjInfoAVVFT;
    4724              : //      grid.attach_to_vertices_dv( aAdjInfoAVVFT, vertexNoInfo );
    4725              : //      Grid::VertexAttachmentAccessor<AttVecVertFracTrip> aaVrtInfoFraTri(grid,  aAdjInfoAVVFT );
    4726              : 
    4727              :         // Lebendigmachung in:
    4728              :         //      for( auto & fsfpmv : fracSubdom_facePerpendMinVal ) .....
    4729              :         // von dort lernen!!!!!
    4730              : 
    4731              :         // notwendig: face, normal, volume, edge
    4732              : 
    4733              :         // TODO FIXME das wollen wir nicht, sondern das alte Vertex Fracture Triple
    4734              : //      m_vrtxFractrQuadrplVec = VrtxFractrQuadrplArte3DVec();
    4735              :         // TODO FIXME diese Einträge erzeugen
    4736              : 
    4737              :         // TODO FIXME kann vielleicht vereinfacht werden durch einen Loop über alle Vertizes,
    4738              :         // und das Abfragen der dort schon gespeicherten vertex property Geschichten, sonst
    4739              :         // wird manches doppelt gemoppelt
    4740              :         
    4741              :         for( auto const & fracInf : m_fracInfos )
    4742              :         {
    4743              :                 IndexType fracSudo = fracInf.subsetIndex;
    4744              : 
    4745              : 
    4746              : //              for(EdgeIterator iterEdg = m_sh.begin<Edge>(fracIndSudo); iterEdg != m_sh.end<Edge>(fracIndSudo); iterEdg++ )
    4747              : //
    4748              :                 for( FaceIterator iterFac = m_sh.begin<Face>(fracSudo); iterFac != m_sh.end<Face>(fracSudo); iterFac++ )
    4749              :                 {
    4750              : 
    4751              : //                      VrtxFractrQuadrplArte3D vrtxFractrQuadrpl;
    4752              :                         
    4753              :                         // TODO FIXME die Innereien dieses Loops irgendwie für boundary faces hinbiegen,
    4754              :                         // vermutlich nicht viel verändern, dafür eigene Routine, die dann für jeweils ein face den
    4755              :                         // Müll umsetzt
    4756              : 
    4757              :                         Face* fac = *iterFac;
    4758              :                         
    4759              :                         auto sudoFacInnerLoop = m_sh.get_subset_index(fac);
    4760              :                         
    4761              :                         if( sudoFacInnerLoop != fracSudo )
    4762              :                                 UG_THROW("Subdomain Index Fehler 3D " << std::endl);
    4763              : 
    4764              : //                      std::vector<Vertex*> verticesFac;
    4765              : //
    4766              : //                      for( IndexType i = 0; i < fac->num_vertices(); i++ )
    4767              : //                      {
    4768              : //                              verticesFac.push_back( fac->vertex(i) );
    4769              : //                      }
    4770              : 
    4771              : 
    4772              :                         std::vector<Volume*> assoVols;
    4773              : 
    4774              :                         // wo kam denn der Käse her?
    4775              : //                      if( ! m_grid.option_is_enabled(FACEOPT_STORE_ASSOCIATED_VOLUMES) )
    4776              : //                              UG_THROW("How to collect asso vols?" << std::endl);
    4777              : 
    4778              :                         // brauchen wir das? für was? von SR irgendwie übernommen, wo dort was entfernt ähnliches gemacht wird....
    4779              :                         if(! m_grid.option_is_enabled(VOLOPT_AUTOGENERATE_FACES) )
    4780              :                         {
    4781              :                                 UG_LOG("WARNING grid option VOLOPT_AUTOGENERATE_FACES autoenabled.\n");
    4782              :                                 m_grid.enable_options(VOLOPT_AUTOGENERATE_FACES);
    4783              :                         }
    4784              : 
    4785              : 
    4786              : //                      for( Grid::AssociatedVolumeIterator volIt  = m_grid.associated_volumes_begin(fac);
    4787              : //                                                                                              volIt != m_grid.associated_volumes_end(fac);
    4788              : //                                                                                              volIt++
    4789              : //                      )
    4790              : //                      {
    4791              : //                              assoVols.push_back(*volIt);
    4792              : //                      }
    4793              : 
    4794              :                         CollectVolumes(assoVols, m_grid, fac );
    4795              : //
    4796              : //                      for( auto const & av : assoVols )
    4797              : //                      {
    4798              : //                              m_sh.assign_subset(av, m_sh.num_subsets());
    4799              : //                      }
    4800              : //
    4801              : //                      return true;
    4802              : 
    4803              : //                      using VolNormPair = std::pair< Volume*, vector3 >;
    4804              : //
    4805              : //                      using VecVolNormPair = std::vector<VolNormPair>;
    4806              : //
    4807              : //                      VecVolNormPair vecNormalsAwayVol;
    4808              : 
    4809              : //                      UG_LOG("Center Face " << CalculateCenter(fac,m_aaPos) << std::endl);
    4810              : 
    4811              :                         for( auto const & kuhVol : assoVols )
    4812              :                         {
    4813              :                                 bool facFound = false;
    4814              :                                 IndexType numFd = 0;
    4815              : 
    4816              :                                 for( IndexType iSide = 0; iSide < kuhVol->num_sides(); iSide++ )
    4817              :                                 {
    4818              :                                         Face * kuhFac = m_grid.get_side(kuhVol, iSide);
    4819              : 
    4820              : //                                      UG_LOG("Center Kuh Face " << CalculateCenter(kuhFac,m_aaPos) << std::endl);
    4821              : 
    4822              :                                         // TODO FIXME eigentliches Ziel ist es, den face descriptor des Volumens zu finden,
    4823              :                                         // das mit dem face übereinstimmt, alle anderen Seiten des Volumens sind egal
    4824              :                                         // Funktion suchen, die ausgehend von einem Face, das ein Volumen begrenzt,
    4825              :                                         // den zum Volumen passenden FaceDescriptor findet, also auch richtige Orientierung
    4826              :                                         // der Vertices beinhaltet
    4827              :                                         // FRAGE TODO FIXME ist ein face descriptor von der Orientierung zum Volumen abhängig
    4828              :                                         // oder hängt der nur vom Face ab, das eine vorgegebene Oriertierung hat?
    4829              : 
    4830              :                                         bool checkCoincide = checkIfFacesVerticesCoincide( kuhFac, fac );
    4831              : 
    4832              :                                         if( checkCoincide )
    4833              :                                         {
    4834              :                                                 facFound = true;
    4835              :                                                 numFd++;
    4836              : 
    4837              :                                                 if( kuhFac != fac )
    4838              :                                                         UG_LOG("Kuh Fac ist nicht fac " << std::endl);
    4839              : 
    4840              :                                                 FaceDescriptor facDescr;
    4841              : 
    4842              :                                                 // TODO FIXME testen, ob der Face Descriptor von der Orientierung abhängt
    4843              :                                                 // also testen, ob sich der face descriptor ändert, wenn das Volumen
    4844              :                                                 // auf der einen und auf der anderen Seite des faces hängt
    4845              :                                                 // deswegen auch die ganze Prozedur mit den kuhFacs, die hoffentlich
    4846              :                                                 // je nach Volumen anders orientiert sind als das eigentliche Face,
    4847              :                                                 // aber dieselben Vertices haben, also geometrisch gleich sind, aber anders orientiert!!!!
    4848              : 
    4849              :                                                 // TODO FIXME andere Hergehensweise vielleicht:
    4850              :                                                 // von m_aaVrtInfoAssoVols ausgehen, darüber loopen, oder die in einen Vektor stecken,
    4851              :                                                 // wo die Vertices dabei sind, dann kann man sich vielelicht ein paar Klimmzüge sparen,
    4852              :                                                 // vielleicht aber auch nicht.....
    4853              : 
    4854              :                                                 kuhVol->face_desc( iSide, facDescr );
    4855              : 
    4856              :                                                 vector3 normal;
    4857              : 
    4858              :                                                 CalculateNormal( normal, & facDescr, m_aaPos );
    4859              : 
    4860              :                                                 vector3 facCenter = CalculateCenter( kuhFac, m_aaPos );
    4861              :                                                 vector3 kuhCenter = CalculateCenter( fac, m_aaPos );
    4862              :                                                 vector3 kuhVolCenter = CalculateCenter( kuhVol, m_aaPos);
    4863              : 
    4864              : //                                              UG_LOG("Normale zum face descriptor " << normal << " , " << facCenter << std::endl);
    4865              : //                                              UG_LOG("Normale zum Kuhh descriptor " << normal << " , " << kuhCenter << std::endl);
    4866              : //                                              UG_LOG("Zentrum des Vol")
    4867              : 
    4868              : //                                              UG_LOG("fac " << fac << std::endl );
    4869              : //                                              UG_LOG("kuh " << kuhFac << std::endl );
    4870              : 
    4871              :                                                 UG_LOG("Normale ist " << normal << " fac " << facCenter
    4872              :                                                                 << " vol " << kuhVolCenter << std::endl);
    4873              : 
    4874              : 
    4875              : //                                              VolNormPair normalsAwayVol( kuhVol, normal );
    4876              : //
    4877              : //                                              vecNormalsAwayVol.push_back( normalsAwayVol );
    4878              : 
    4879              :                                                 std::vector<Edge*> facEdgs;
    4880              : 
    4881              :                                                 CollectEdges( facEdgs, m_grid, fac);
    4882              : 
    4883              :                                                 for( IndexType iF = 0; iF < fac->num_vertices(); iF++ )
    4884              :                                                 {
    4885              :                                                         Vertex * vrt = fac->vertex(iF);
    4886              : 
    4887              :                         //                              verticesFac.push_back(vrt);
    4888              : 
    4889              :                                                         std::vector<Edge*> edgOfVrtx;
    4890              : 
    4891              :                                                         for( auto const & edg : facEdgs )
    4892              :                                                         {
    4893              :                                                                 if( EdgeContains(edg, vrt) )
    4894              :                                                                 {
    4895              :                                                                         edgOfVrtx.push_back(edg);
    4896              :                                                                 }
    4897              :                                                         }
    4898              : 
    4899              :                                                         if( edgOfVrtx.size() == 2 )
    4900              :                                                         {
    4901              :                                                                 EdgePair commonEdges(edgOfVrtx[0], edgOfVrtx[1]); //  fill values
    4902              :                                                                 // edges commun between face and volume, with the vertex included as well, i.e. two possibilities
    4903              : 
    4904              :                                                                 // TODO FIXME diese Info muss woanders hin, in der AttachedFractFaceEdgeSudo Klasse speichern!
    4905              :                                                                 VertFracTrip infoVerticesThisFace( fac, fracSudo, kuhVol, normal, commonEdges );
    4906              : 
    4907              :                                                                 // TODO FIXME hier irgendwie graphische Ausgabe von irgendwas
    4908              : 
    4909              :                                                                 m_aaVrtInfoFraTri[vrt].push_back( infoVerticesThisFace );
    4910              : 
    4911              :                                                                 // DEBUG OUTPUT; REMOVE LATER
    4912              : //                                                              m_sh.assign_subset(kuhVol,m_sh.num_subsets());
    4913              :                                                         }
    4914              :                                                         else
    4915              :                                                         {
    4916              :                                                                 UG_THROW("Mein Face das hat keine Ecken, keine Ecken hat mein Face" << std::endl);
    4917              :                                                         }
    4918              :                                                 }
    4919              : 
    4920              :                                         }
    4921              :                                 }
    4922              : 
    4923              :                                 if( ! facFound || numFd != 1 )
    4924              :                                 {
    4925              :                                         UG_THROW("Kein Kuh Volumen gefunden" << std::endl);
    4926              :                                         return false;
    4927              :                                 }
    4928              : 
    4929              :                         }
    4930              : 
    4931              :                 }
    4932              : 
    4933              : 
    4934              :         }
    4935              : 
    4936              :         UG_LOG("GEnerierung gelungen " << std::endl);
    4937              : 
    4938              :         return true;
    4939              : }
    4940              : #endif
    4941              : 
    4942            0 : bool ArteExpandFracs3D::checkIfFacesVerticesCoincide( Face * const & facOne, Face * const & facTwo )
    4943              : {
    4944              : 
    4945            0 :         if( facOne->size() != facTwo->size() )
    4946              :                 return false;
    4947              : 
    4948              :         std::vector<Vertex* > facOneVrtcs, facTwoVrtcs;
    4949              : 
    4950            0 :         collectFaceVertices( facOneVrtcs, facOne );
    4951            0 :         collectFaceVertices( facTwoVrtcs, facTwo );
    4952              : 
    4953            0 :         for( auto const & vrtOne : facOneVrtcs )
    4954              :         {
    4955              :                 bool found = false;
    4956              : 
    4957              :                 IndexType numFd = 0;
    4958              : 
    4959            0 :                 for( auto const & vrtTwo : facTwoVrtcs )
    4960              :                 {
    4961            0 :                         if( vrtOne == vrtTwo )
    4962              :                         {
    4963              :                                 found = true;
    4964            0 :                                 numFd++;
    4965              :                         }
    4966              :                 }
    4967              : 
    4968            0 :                 if( ! found || numFd != 1 )
    4969              :                         return false;
    4970              :         }
    4971              : 
    4972              :         return true;
    4973            0 : }
    4974              : 
    4975            0 : bool ArteExpandFracs3D::collectFaceVertices( std::vector<Vertex*> & facVrt, Face * const & fac )
    4976              : {
    4977            0 :         if( fac == nullptr )
    4978              :                 return false;
    4979              : 
    4980              :         facVrt.clear();
    4981              : 
    4982            0 :         for( IndexType iF = 0; iF < fac->num_vertices(); iF++ )
    4983              :         {
    4984            0 :                 Vertex * vrt = fac->vertex(iF);
    4985              : 
    4986            0 :                 facVrt.push_back( vrt );
    4987              :         }
    4988              : 
    4989              :         return true;
    4990              : }
    4991              : 
    4992              : 
    4993              : 
    4994              : 
    4995              : // major function of new grid generation, in Keil Style, but functional grid, only the diamonds have to be
    4996              : // established in additional functionalities independent of this function
    4997            0 : bool ArteExpandFracs3D::loop2EstablishNewVertices()
    4998              : {
    4999            0 :         m_vecCrossVrtInf = std::vector<CrossVertInf>();
    5000              : 
    5001              : 
    5002              :         // TODO FIXME sowas von der Art wird nötig sein als Vorbereitung für die Diamanten,
    5003              :         // Infos darin speichern, vielleicht auch noch notwendig, die Kanten zu speichern oder die faces,
    5004              :         // zu klären im Laufe der Implementation
    5005              :         // std::vector<CrossVertInf > vecCrossVrtInf;
    5006              : 
    5007              :         // zentraler Loop
    5008              : 
    5009              :         // TODO FIXME vorher noch den attVrtVec und den aaVrtVecFac analog implementieren, das fehlt noch!!!
    5010              :         // ebenso seine Befüllung, braucht noch eine Funktion dazwischen, die attachments selber in die
    5011              :         // attach Funktion natürlich
    5012              :         
    5013              :         int untilVrt = 0;
    5014              : 
    5015            0 :         for( VertexIterator iterV = m_sel.begin<Vertex>(); iterV != m_sel.end<Vertex>(); ++ iterV )
    5016              :         {
    5017            0 :                 Vertex * oldVrt = *iterV;
    5018              : 
    5019              :                 // Position dieses Vertex
    5020              :                 vector3 posOldVrt = m_aaPos[oldVrt];
    5021              : 
    5022              :                 // TODO FIXME diese Funktion mit Leben und Analytischer Geometrie 13. Klasse füllen
    5023              : 
    5024              : //              VecVertFracTrip & vecVertFracTrip = m_aaVrtInfoFraTri[oldVrt];
    5025              : //
    5026              : //              std::vector<Edge*> & allAssoEdges = m_aaVrtInfoAssoEdges[oldVrt];
    5027              : //              std::vector<Face*> & allAssoFaces = m_aaVrtInfoAssoFaces[oldVrt];
    5028              : //              std::vector<Volume*> & allAssoVolumes = m_aaVrtInfoAssoVols[oldVrt];
    5029              : 
    5030            0 :                 UG_LOG("vertex at " << posOldVrt << std::endl);
    5031              : 
    5032            0 :                 VecSegmentLimitingSides & vecSegmLimSid = m_vrtxAttAccsVecSegmLimSid[oldVrt];
    5033              : 
    5034            0 :                 for( SegmentLimitingSides const & sls : vecSegmLimSid )
    5035              :                 {
    5036            0 :                         if( sls.hasUnclosedFaces())
    5037              :                                 UG_LOG("Hier hat das Gesicht noch ungeschlossene " << std::endl);
    5038              :                 }
    5039              : 
    5040              : //              if( ! vrtxIsBndVrt )
    5041              : //              {
    5042            0 :                 if( ! establishNewVertizesStasiBased(oldVrt) )
    5043              :                 {
    5044              :                         UG_LOG("Vertex Erzeugung schief gegangen " << std::endl);
    5045            0 :                         return false;
    5046              :                 }
    5047              : 
    5048              : //              }
    5049              : 
    5050              : 
    5051              :                 
    5052              : 
    5053              :         }
    5054              : 
    5055              :         // for debugging
    5056              : //      return false;
    5057              : 
    5058            0 :         return true;
    5059              : }
    5060              : 
    5061              : ////////////////////////////////////////////////////////////////////
    5062              : 
    5063              : #if 0
    5064              : bool ArteExpandFracs3D::establishNewVertizesStasiBased( Vertex * const & oldVrt)
    5065              : {
    5066              :         // anfangs nur für innere Vertizes mit einer fracture
    5067              : 
    5068              :         VecSegmentVolElmInfo & vecSegVolElmInf = m_accsAttVecSegVolElmInfo[oldVrt];
    5069              : 
    5070              :         if( vecSegVolElmInf.size() < 2 )
    5071              :         {
    5072              :                 UG_LOG("nur ein Segment, aber will frische Vertizes?" << std::endl);
    5073              : //              UG_THROW("nur ein Segment, aber will frische Vertizes?" << std::endl);
    5074              : //              return false;
    5075              :                 return true;
    5076              :         }
    5077              : 
    5078              :         for( SegmentVolElmInfo const & svei : vecSegVolElmInf )
    5079              :         {
    5080              :                 // count the number of the fracture subdomains surrounding the segment
    5081              :                 // in case of boundary vertex, also count the number of boundary subdomains
    5082              : 
    5083              :                 std::vector<IndexType> sudosInSegment;
    5084              : 
    5085              :                 if( ! extracFractSudosOfSegment( svei, sudosInSegment ) )
    5086              :                 {
    5087              :                         UG_LOG("kann sudos nicht extrahieren " << std::endl);
    5088              :                         UG_THROW("kann sudos nicht extrahieren " << std::endl);
    5089              :                         return false;
    5090              :                 }
    5091              : 
    5092              :                 IndexType sudoNumInSeg = sudosInSegment.size();
    5093              : 
    5094              :                 // check if is boundary vertex
    5095              : 
    5096              :                 auto & vrtxFracPrps = m_aaMarkVrtVFP[ oldVrt ];
    5097              : 
    5098              :                 bool vrtxIsBndVrt = vrtxFracPrps.getIsBndFracVertex();
    5099              : 
    5100              :                 UG_LOG("is bndry " << vrtxIsBndVrt << std::endl);
    5101              : 
    5102              :                 if( ! vrtxIsBndVrt )
    5103              :                 {
    5104              :                         // count number of fracture subdomains in the Segment, should have been done before......
    5105              : 
    5106              :                         // TODO FIXME ersetze das altmodische VrtxFracProptsStatus durch ein Zählen
    5107              :                         // der subdomains, die pro Segment wirklich vorkommen, nachdem die
    5108              :                         // auslaufenden fracture faces den generellen Faces zugeschlagen worden sind
    5109              :                         // diese Zählweise ist die erste Folgeaufgabe, damit der komische vrtxFractureProperties Status
    5110              :                         // weg geworfen werden kann, der ist nämlich nutzlos inzwischen, da er auch auslaufende
    5111              :                         // fracture faces zählt, was Unsinn ist.......
    5112              :                         // später folgt auch die Verallgemeinerung auf boundary vertizes, dann muss deren Wahl
    5113              :                         // vielleicht wieder dazu genommen werden.....
    5114              : 
    5115              :                         //Vorbereitung Ersetzung VertexFractureProperties Status
    5116              :                         // durch Zählen der Fracture Subdomains von jedem Segment
    5117              :                         // die Zählerei kann dann gemacht werden, wenn die doppelten offenen fracture faces
    5118              :                         // in die allgemeinen faces verschoben werden, dann geht das in einem Abwasch,
    5119              :                         // gehe dazu in die entsprechende Funktion
    5120              : 
    5121              : //                      if( vrtxFracPrps.getVrtxFracStatus() == VrtxFracProptsStatus::oneFracSuDoAtt )
    5122              :                         if( sudoNumInSeg == 1 )
    5123              :                         {
    5124              :                                 // standard case, one fracture
    5125              :                                 if( ! expandWithinTheSegment<1,false>( oldVrt, svei ) )
    5126              :                                 {
    5127              :                                         UG_LOG("Expandierung einfachster Fall schief gegangen " << std::endl);
    5128              :                                         return false;
    5129              :                                 }
    5130              :                         }
    5131              :                         else // unterscheiden zwei und drei vermutlich..... aber wichtiger Segmentzahl..... und dann kommt es darauf an, wieviele subdoms im einzelnen Segment sind
    5132              :                         {
    5133              : 
    5134              :                         }
    5135              : 
    5136              :                 }
    5137              :                 else
    5138              :                 {
    5139              :                         // boundary faces counted as fracture faces, but no expansion
    5140              :                         // zuerst aber die inneren Schnittvertizes, weil bei denen die Nicht-Null Expansion
    5141              :                         // gelernt werden kann, dann anzuwenden auf Null-Expansion senkrecht zu den boundaries......
    5142              :                 }
    5143              : 
    5144              :         }
    5145              : 
    5146              :         return true;
    5147              : }
    5148              : #endif
    5149              : 
    5150              : ///////////////////////////////////////////////////////////////////
    5151              : 
    5152            0 : bool ArteExpandFracs3D::establishSegmentLimitingSidesInfo()
    5153              : {
    5154              : 
    5155              :         UG_LOG("ESTABLISH SGEMENT LIM SIDE INFO" << std::endl );
    5156              : 
    5157            0 :         for( VertexIterator iterV = m_sel.begin<Vertex>(); iterV != m_sel.end<Vertex>(); ++ iterV )
    5158              :         {
    5159              :                 Vertex * oldVrt = *iterV;
    5160              : 
    5161            0 :                 UG_LOG("establish segm lim sides for " << m_aaPos[oldVrt] << std::endl);
    5162              : 
    5163              :                 VecSegmentLimitingSides & vecSegmLimSid = m_vrtxAttAccsVecSegmLimSid[oldVrt];
    5164              : 
    5165              :                 UG_LOG("Segment limiting sides got " << std::endl);
    5166              : 
    5167              :                 auto & vrtxFracPrps = m_aaMarkVrtVFP[ oldVrt ];
    5168              : 
    5169              :                 bool vrtxIsBndVrt = vrtxFracPrps.getIsBndFracVertex();
    5170              : 
    5171              :                 UG_LOG("is bndry " << vrtxIsBndVrt << std::endl);
    5172              : 
    5173              :                 VecSegmentVolElmInfo & vecSegVolElmInf = m_accsAttVecSegVolElmInfo[oldVrt];
    5174              : 
    5175              :                 UG_LOG("CHECK SIZE" << std::endl);
    5176              : 
    5177            0 :                 if( vecSegVolElmInf.size() < 2 )
    5178              :                 {
    5179              :                         UG_LOG("nur ein Segment, aber will frische Vertizes?" << std::endl);
    5180              :         //              UG_THROW("nur ein Segment, aber will frische Vertizes?" << std::endl);
    5181              :         //              return false;
    5182              : //                      return true;
    5183              :                         continue;
    5184              :                 }
    5185              : 
    5186              :                 UG_LOG("CONTINUED" << std::endl);
    5187              : 
    5188            0 :                 for( SegmentVolElmInfo const & segVolsElInf : vecSegVolElmInf )
    5189              :                 {
    5190              :                         // count the number of the fracture subdomains surrounding the segment
    5191              :                         // in case of boundary vertex, also count the number of boundary subdomains
    5192              : 
    5193              :         //              std::vector<IndexType> sudosInSegment;
    5194              : 
    5195              :                         // hier die neue Klasse und ihr averaing einführen, oder im Hauptloop der neuen Elemente.....
    5196              :                         // SegmentSides<....> in .h file für die richtigen template parameter Kurznamen geben und hier
    5197              :                         // Objekt erstellen und je nach ob mit oder ohne Bndry entsprechend aufladen und averagen.....
    5198              :                         // und zwar für jedes Segment einzeln, und abhängig von boundary oder nicht die boundary Geschichten
    5199              :                         // dazu oder auch nicht...... also einen VecSegmentSides erstellen auch, das einzelne Objekt
    5200              :                         // weiss dann, ob es eine Boundary ist..... vielleicht noch den Vektor dazu als übergebener Parameter
    5201              :                         // damit man den da drin weiter reichen kann?
    5202              :                         // wenn jedes Objekt des Vektors von SegmentSIdes sowohl seinen Vertex kennt als auch weiss,
    5203              :                         // ob es boundary oder nicht ist, kann danach darüber geloopt werden, ohne nochmal
    5204              :                         // aussen den Vertex mit geben zu müssen, oder die Info, ob bndry oder nicht.....
    5205              :                         // danach gibts dann Funktionen, die alleine ein Objekt von der Sorte SegmentSides schlucken brauchen
    5206              :                         // und hier nur ein Loop über den ganzen Vektor davon, wo für jedes Element dann die Fkt aufgerufen wird....
    5207              : 
    5208              :                         SegmentLimitingSides segLimSids( oldVrt, vrtxIsBndVrt );
    5209              : 
    5210              :         //              std::vector<Volume*> vecVolsOfSegment;
    5211              : 
    5212              :                         IndexType boundarySites = 0;
    5213              : 
    5214            0 :                         for( AttachedVolumeElemInfo const & volElmInf : segVolsElInf )
    5215              :                         {
    5216            0 :                                 if( ! segLimSids.schluckVecAttFractElm( volElmInf.getVecFractManifElem() ) )
    5217              :                                 {
    5218              :                                         UG_LOG("schlucken schief gegangen " << std::endl);
    5219            0 :                                         UG_THROW("schlucken schief gegangen " << std::endl);
    5220              :                                         return false;
    5221              :                                 }
    5222              : 
    5223              : 
    5224            0 :                                 if( volElmInf.hasUnclosedFracture() )
    5225              :                                 {
    5226            0 :                                         if( ! segLimSids.schluckVecAttUnclosedFractElm( volElmInf.getVecUnclosedFractManifElem() ) )
    5227              :                                         {
    5228              :                                                 UG_LOG("Schlucken von unclosed schief gegangen " << std::endl);
    5229              : //                                              UG_THROW("Schlucken von unclosed schief gegangen " << std::endl);
    5230              : //                                              return false;
    5231              :                                         }
    5232              :                                         else
    5233              :                                         {
    5234              :                                                 UG_LOG("ungeschlossene fracture geschluckt " << std::endl);
    5235              :                                         }
    5236              : 
    5237            0 :                                         if( ! segLimSids.hasUnclosedFaces() )
    5238              :                                         {
    5239              :                                                 UG_LOG("keine ungeschlossenen Gesichter " << std::endl);
    5240            0 :                                                 UG_THROW("keine ungeschlossenen Gesichter " << std::endl);
    5241              :                                         }
    5242              :                                 }
    5243              : 
    5244            0 :                                 if( vrtxIsBndVrt )
    5245              :                                 {
    5246              :                                         auto vecBndryManifelm = volElmInf.getVecBndryManifElem();
    5247              : 
    5248            0 :                                         IndexType sizeVecBndryManifElm = volElmInf.getVecBndryManifElem().size();
    5249              : 
    5250            0 :                                         boundarySites += sizeVecBndryManifElm;
    5251              : 
    5252              :         //                              if( ! segLimSids.schluckVecAttBndryElm( volElmInf.getVecBndryManifElem() ) )
    5253            0 :                                         if( ! segLimSids.schluckVecAttBndryElm( vecBndryManifelm ) )
    5254              :                                         {
    5255              :                                                 UG_LOG("schlucken B schief gegangen " << std::endl);
    5256            0 :                                                 UG_THROW("schlucken B schief gegangen " << std::endl);
    5257              :                                                 return false;
    5258              :                                         }
    5259              : 
    5260              :                                         // TODO FIXME es muss abgefangen werden, wenn bei einem boundary vertex gar keine boundary Seiten da sind
    5261              :         //                              if( (volElmInf.getVecBndryManifElem()).size() == 0  )
    5262            0 :                                         if( sizeVecBndryManifElm == 0  )
    5263            0 :                                                 UG_LOG("Grenze verloren gegangen " << m_aaPos[oldVrt] << std::endl);
    5264            0 :                                 }
    5265              : 
    5266              :                                 Volume * vol2Add = volElmInf.getFulldimElem();
    5267              :                                 segLimSids.schluckFulldimElem(vol2Add);
    5268              :                         }
    5269              : 
    5270            0 :                         if( vrtxIsBndVrt && boundarySites == 0 )
    5271              :                         {
    5272            0 :                                 UG_LOG("No boundary sites at " << m_aaPos[oldVrt] << std::endl);
    5273            0 :                                 UG_THROW("No boundary sites at " << m_aaPos[oldVrt] << std::endl);
    5274              :                         }
    5275              : 
    5276            0 :                         if( ! segLimSids.averageAll() )
    5277              :                         {
    5278              :                                 UG_LOG("keine Mittelung " << std::endl);
    5279            0 :                                 UG_THROW("keine Mittelung " << std::endl);
    5280              :                                 return false;
    5281              :                         }
    5282              : 
    5283            0 :                         vecSegmLimSid.push_back(segLimSids);
    5284            0 :                 }
    5285              : 
    5286              : 
    5287              :         }
    5288              : 
    5289              :         UG_LOG("END ESTABLISH SGEMENT LIM SIDE INFO" << std::endl );
    5290              : 
    5291              : 
    5292              :         return true;
    5293              : }
    5294              : 
    5295              : ///////////////////////////////////////////////////////////////////////
    5296              : 
    5297            0 : bool ArteExpandFracs3D::establishNewVertizesStasiBased( Vertex * const & oldVrt)
    5298              : {
    5299              : 
    5300            0 :         auto & vrtxFracPrps = m_aaMarkVrtVFP[ oldVrt ];
    5301              : 
    5302              :         bool vrtxIsBndVrt = vrtxFracPrps.getIsBndFracVertex();
    5303              : 
    5304              :         UG_LOG("is bndry " << vrtxIsBndVrt << std::endl);
    5305              : 
    5306              : 
    5307              : //      VecSegmentVolElmInfo & vecSegVolElmInf = m_accsAttVecSegVolElmInfo[oldVrt];
    5308              : //
    5309              : //      if( vecSegVolElmInf.size() < 2 )
    5310              : //      {
    5311              : //              UG_LOG("nur ein Segment, aber will frische Vertizes?" << std::endl);
    5312              : ////            UG_THROW("nur ein Segment, aber will frische Vertizes?" << std::endl);
    5313              : ////            return false;
    5314              : //              return true;
    5315              : //      }
    5316              : 
    5317            0 :         VecSegmentLimitingSides & vecSegmLimSid = m_vrtxAttAccsVecSegmLimSid[oldVrt];
    5318              : 
    5319            0 :         if(  vecSegmLimSid.size() == 0 )
    5320              :         {
    5321              :                 UG_LOG("keine verschiedenen Segmente" << std::endl);
    5322            0 :                 return true;
    5323              :         }
    5324              : 
    5325            0 :         if( vecSegmLimSid.size() == 1 )
    5326              :         {
    5327              :                 UG_LOG("sonderbarer Fall von nur einem Segment " << std::endl );
    5328            0 :                 UG_THROW("sonderbarer Fall von nur einem Segment " << std::endl );
    5329              :                 return false;
    5330              :         }
    5331              : 
    5332            0 :         for( SegmentLimitingSides & segLimSids : vecSegmLimSid )
    5333              :         {
    5334              : 
    5335            0 :                 if( segLimSids.hasUnclosedFaces() )
    5336              :                 {
    5337              :                         UG_LOG("beim ausdehnen ungeschlossene Gesichter " << std::endl);
    5338              :                 }
    5339              : 
    5340            0 :                 if( ! expandWithinTheSegment( segLimSids ) )
    5341              :                 {
    5342              :                         UG_LOG("schief gegangen Vertex Erzeugung " << std::endl);
    5343              :                         //UG_THROW("schief gegangen Vertex Erzeugung " << std::endl);
    5344              :                         return false;
    5345              :                 }
    5346              :         }
    5347              : 
    5348              :         // collect information for diamonds already now, get the crossing points
    5349              : 
    5350              :         bool isCrossingPt = ( vecSegmLimSid.size() > 2 );
    5351              : 
    5352            0 :         if( isCrossingPt )
    5353            0 :                 m_vrtcsCrossingPts.push_back(oldVrt);
    5354              : 
    5355              :         UG_LOG("Vertex creation hat funktioniert " << std::endl);
    5356              :         //      UG_THROW("Vertex creation failed " << std::endl);
    5357              : 
    5358            0 :         return true;
    5359              : 
    5360              : }
    5361              : 
    5362              : /////////////////////////////////////////////////////////////////
    5363              : 
    5364              : #if 0
    5365              : 
    5366              : bool ArteExpandFracs3D::establishNewVertizesStasiBased( Vertex * const & oldVrt)
    5367              : {
    5368              :         // anfangs nur für innere Vertizes mit einer fracture
    5369              : 
    5370              :         // testweise, später verallgemeinert mit den Boundary faces
    5371              : 
    5372              :         auto & vrtxFracPrps = m_aaMarkVrtVFP[ oldVrt ];
    5373              : 
    5374              :         bool vrtxIsBndVrt = vrtxFracPrps.getIsBndFracVertex();
    5375              : 
    5376              :         UG_LOG("is bndry " << vrtxIsBndVrt << std::endl);
    5377              : 
    5378              : //      if( vrtxIsBndVrt )
    5379              : //      {
    5380              : //              UG_LOG("boundary noch zu lösen, bisher nix machen" << std::endl);
    5381              : //              return true;
    5382              : //      }
    5383              : 
    5384              :         VecSegmentVolElmInfo & vecSegVolElmInf = m_accsAttVecSegVolElmInfo[oldVrt];
    5385              : 
    5386              :         if( vecSegVolElmInf.size() < 2 )
    5387              :         {
    5388              :                 UG_LOG("nur ein Segment, aber will frische Vertizes?" << std::endl);
    5389              : //              UG_THROW("nur ein Segment, aber will frische Vertizes?" << std::endl);
    5390              : //              return false;
    5391              :                 return true;
    5392              :         }
    5393              : 
    5394              : 
    5395              :         for( SegmentVolElmInfo const & segVolsElInf : vecSegVolElmInf )
    5396              :         {
    5397              :                 // count the number of the fracture subdomains surrounding the segment
    5398              :                 // in case of boundary vertex, also count the number of boundary subdomains
    5399              : 
    5400              : //              std::vector<IndexType> sudosInSegment;
    5401              : 
    5402              :                 // hier die neue Klasse und ihr averaing einführen, oder im Hauptloop der neuen Elemente.....
    5403              :                 // SegmentSides<....> in .h file für die richtigen template parameter Kurznamen geben und hier
    5404              :                 // Objekt erstellen und je nach ob mit oder ohne Bndry entsprechend aufladen und averagen.....
    5405              :                 // und zwar für jedes Segment einzeln, und abhängig von boundary oder nicht die boundary Geschichten
    5406              :                 // dazu oder auch nicht...... also einen VecSegmentSides erstellen auch, das einzelne Objekt
    5407              :                 // weiss dann, ob es eine Boundary ist..... vielleicht noch den Vektor dazu als übergebener Parameter
    5408              :                 // damit man den da drin weiter reichen kann?
    5409              :                 // wenn jedes Objekt des Vektors von SegmentSIdes sowohl seinen Vertex kennt als auch weiss,
    5410              :                 // ob es boundary oder nicht ist, kann danach darüber geloopt werden, ohne nochmal
    5411              :                 // aussen den Vertex mit geben zu müssen, oder die Info, ob bndry oder nicht.....
    5412              :                 // danach gibts dann Funktionen, die alleine ein Objekt von der Sorte SegmentSides schlucken brauchen
    5413              :                 // und hier nur ein Loop über den ganzen Vektor davon, wo für jedes Element dann die Fkt aufgerufen wird....
    5414              : 
    5415              :                 SegmentLimitingSides segLimSids( oldVrt, vrtxIsBndVrt );
    5416              : 
    5417              : //              std::vector<Volume*> vecVolsOfSegment;
    5418              : 
    5419              :                 IndexType boundarySites = 0;
    5420              : 
    5421              :                 for( AttachedVolumeElemInfo const & volElmInf : segVolsElInf )
    5422              :                 {
    5423              :                         if( ! segLimSids.schluckVecAttFractElm( volElmInf.getVecFractManifElem() ) )
    5424              :                         {
    5425              :                                 UG_LOG("schlucken schief gegangen " << std::endl);
    5426              :                                 UG_THROW("schlucken schief gegangen " << std::endl);
    5427              :                                 return false;
    5428              :                         }
    5429              : 
    5430              :                         if( vrtxIsBndVrt )
    5431              :                         {
    5432              :                                 auto vecBndryManifelm = volElmInf.getVecBndryManifElem();
    5433              : 
    5434              :                                 IndexType sizeVecBndryManifElm = volElmInf.getVecBndryManifElem().size();
    5435              : 
    5436              :                                 boundarySites += sizeVecBndryManifElm;
    5437              : 
    5438              : //                              if( ! segLimSids.schluckVecAttBndryElm( volElmInf.getVecBndryManifElem() ) )
    5439              :                                 if( ! segLimSids.schluckVecAttBndryElm( vecBndryManifelm ) )
    5440              :                                 {
    5441              :                                         UG_LOG("schlucken B schief gegangen " << std::endl);
    5442              :                                         UG_THROW("schlucken B schief gegangen " << std::endl);
    5443              :                                         return false;
    5444              :                                 }
    5445              : 
    5446              :                                 // TODO FIXME es muss abgefangen werden, wenn bei einem boundary vertex gar keine boundary Seiten da sind
    5447              : //                              if( (volElmInf.getVecBndryManifElem()).size() == 0  )
    5448              :                                 if( sizeVecBndryManifElm == 0  )
    5449              :                                         UG_LOG("Grenze verloren gegangen " << m_aaPos[oldVrt] << std::endl);
    5450              :                         }
    5451              : 
    5452              :                         Volume * vol2Add = volElmInf.getFulldimElem();
    5453              :                         segLimSids.schluckFulldimElem(vol2Add);
    5454              :                 }
    5455              : 
    5456              :                 if( vrtxIsBndVrt && boundarySites == 0 )
    5457              :                 {
    5458              :                         UG_LOG("No boundary sites at " << m_aaPos[oldVrt] << std::endl);
    5459              :                         UG_THROW("No boundary sites at " << m_aaPos[oldVrt] << std::endl);
    5460              :                 }
    5461              : 
    5462              :                 if( ! segLimSids.averageAll() )
    5463              :                 {
    5464              :                         UG_LOG("keine Mittelung " << std::endl);
    5465              :                         UG_THROW("keine Mittelung " << std::endl);
    5466              :                         return false;
    5467              :                 }
    5468              : 
    5469              : //              if( vrtxIsBndVrt )
    5470              : //              {
    5471              : //                      if( segLimSids. )
    5472              : //              }
    5473              : 
    5474              : //              for( SegmentLimitSidesPairSudoNorml segLimSiPSN : vecSegmLimSidPrSudoNorml )
    5475              : //              {
    5476              : //
    5477              : //              }
    5478              : 
    5479              : //              expandWithinTheSegment<SegmentVrtxFracStatus::oneFracSuDoAtt>(segLimSids
    5480              : 
    5481              :                 if( ! expandWithinTheSegment(segLimSids) )
    5482              :                 {
    5483              :                         UG_LOG("schief gegangen Vertex Erzeugung " << std::endl);
    5484              :                         UG_THROW("schief gegangen Vertex Erzeugung " << std::endl);
    5485              :                         return false;
    5486              :                 }
    5487              : 
    5488              : //              SegmentVrtxFracStatus segStatFract = segLimSids.spuckCrossingTyp();
    5489              : //
    5490              : //              switch( segStatFract )
    5491              : //              {
    5492              : //                      case SegmentVrtxFracStatus::noFracSuDoAtt :
    5493              : //                      {
    5494              : //                              UG_LOG("is not a fracture, but a segment?" << std::endl);
    5495              : //                              UG_THROW("is not a fracture, but a segment?" << std::endl);
    5496              : //                              return false;
    5497              : //                      }
    5498              : //                      case SegmentVrtxFracStatus::oneFracSuDoAtt :
    5499              : //                      {
    5500              : //                              if( ! expandWithinTheSegment<SegmentVrtxFracStatus::oneFracSuDoAtt,false,false>(segLimSids, vecVolsOfSegment) )
    5501              : //                              {
    5502              : //                                      UG_LOG("Expandierung 1 schief gegangen " << std::endl);
    5503              : //                                      UG_THROW("Expandierung 1 schief gegangen " << std::endl);
    5504              : //                                      return false;
    5505              : //                              }
    5506              : //                              break;
    5507              : //                      }
    5508              : //                      case SegmentVrtxFracStatus::twoFracSuDoAtt :
    5509              : //                      {
    5510              : //                              break; // TODO FIXME implementieren
    5511              : //                      }
    5512              : //                      case SegmentVrtxFracStatus::threeFracSuDoAtt :
    5513              : //                      {
    5514              : //                              if( ! expandWithinTheSegment<SegmentVrtxFracStatus::threeFracSuDoAtt,false,false>(segLimSids, vecVolsOfSegment) )
    5515              : //                              {
    5516              : //                                      UG_LOG("Expandierung 3 schief gegangen " << std::endl);
    5517              : //                                      UG_THROW("Expandierung 3 schief gegangen " << std::endl);
    5518              : //                                      return false;
    5519              : //                              }
    5520              : //                              break;
    5521              : //                      }
    5522              : //                      default :
    5523              : //                      {
    5524              : //                              UG_LOG("strange fracture crossing" << std::endl);
    5525              : //                              UG_THROW("strange fracture crossing?" << std::endl);
    5526              : //                              return false;
    5527              : //                      }
    5528              : //              }
    5529              :         }
    5530              : 
    5531              :         UG_LOG("Vertex creation hat funktioniert " << std::endl);
    5532              :         //      UG_THROW("Vertex creation failed " << std::endl);
    5533              : 
    5534              :         return true;
    5535              : }
    5536              : 
    5537              : #endif
    5538              : 
    5539              : //              if( ! extracFractSudosOfSegment( svei, sudosInSegment ) )
    5540              : //              {
    5541              : //                      UG_LOG("kann sudos nicht extrahieren " << std::endl);
    5542              : //                      UG_THROW("kann sudos nicht extrahieren " << std::endl);
    5543              : //                      return false;
    5544              : //              }
    5545              : //
    5546              : //              IndexType sudoNumInSeg = sudosInSegment.size();
    5547              : //
    5548              : //              // check if is boundary vertex
    5549              : //
    5550              : //              auto & vrtxFracPrps = m_aaMarkVrtVFP[ oldVrt ];
    5551              : //
    5552              : //
    5553              : //              if( ! vrtxIsBndVrt )
    5554              : //              {
    5555              : //                      // count number of fracture subdomains in the Segment, should have been done before......
    5556              : //
    5557              : //                      // TODO FIXME ersetze das altmodische VrtxFracProptsStatus durch ein Zählen
    5558              : //                      // der subdomains, die pro Segment wirklich vorkommen, nachdem die
    5559              : //                      // auslaufenden fracture faces den generellen Faces zugeschlagen worden sind
    5560              : //                      // diese Zählweise ist die erste Folgeaufgabe, damit der komische vrtxFractureProperties Status
    5561              : //                      // weg geworfen werden kann, der ist nämlich nutzlos inzwischen, da er auch auslaufende
    5562              : //                      // fracture faces zählt, was Unsinn ist.......
    5563              : //                      // später folgt auch die Verallgemeinerung auf boundary vertizes, dann muss deren Wahl
    5564              : //                      // vielleicht wieder dazu genommen werden.....
    5565              : //
    5566              : //                      //Vorbereitung Ersetzung VertexFractureProperties Status
    5567              : //                      // durch Zählen der Fracture Subdomains von jedem Segment
    5568              : //                      // die Zählerei kann dann gemacht werden, wenn die doppelten offenen fracture faces
    5569              : //                      // in die allgemeinen faces verschoben werden, dann geht das in einem Abwasch,
    5570              : //                      // gehe dazu in die entsprechende Funktion
    5571              : //
    5572              : ////                    if( vrtxFracPrps.getVrtxFracStatus() == VrtxFracProptsStatus::oneFracSuDoAtt )
    5573              : //                      if( sudoNumInSeg == 1 )
    5574              : //                      {
    5575              : //                              // standard case, one fracture
    5576              : //                              if( ! expandWithinTheSegment<1,false>( oldVrt, svei ) )
    5577              : //                              {
    5578              : //                                      UG_LOG("Expandierung einfachster Fall schief gegangen " << std::endl);
    5579              : //                                      return false;
    5580              : //                              }
    5581              : //                      }
    5582              : //                      else // unterscheiden zwei und drei vermutlich..... aber wichtiger Segmentzahl..... und dann kommt es darauf an, wieviele subdoms im einzelnen Segment sind
    5583              : //                      {
    5584              : //
    5585              : //                      }
    5586              : //
    5587              : //              }
    5588              : //              else
    5589              : //              {
    5590              : //                      // boundary faces counted as fracture faces, but no expansion
    5591              : //                      // zuerst aber die inneren Schnittvertizes, weil bei denen die Nicht-Null Expansion
    5592              : //                      // gelernt werden kann, dann anzuwenden auf Null-Expansion senkrecht zu den boundaries......
    5593              : //              }
    5594              : //
    5595              : //      }
    5596              : 
    5597              : //      UG_LOG("Vertex creation failed " << std::endl);
    5598              : //      UG_THROW("Vertex creation failed " << std::endl);
    5599              : //
    5600              : //
    5601              : //      return false;
    5602              : //
    5603              : 
    5604              : 
    5605              : ////////////////////////////////////////////////////////////////////
    5606              : 
    5607              : #if 0
    5608              : bool ArteExpandFracs3D::extracFractSudosOfSegment( SegmentVolElmInfo const & segmVolElmInfo, std::vector<ArteExpandFracs3D::IndexType> & sudosInSegment )
    5609              : {
    5610              : 
    5611              : 
    5612              :         VecAttachedFractFaceEdgeSudo vecAttFractFaces;
    5613              : 
    5614              :         for( AttachedVolumeElemInfo const & avei : segmVolElmInfo )
    5615              :         {
    5616              :                 VecAttachedFractFaceEdgeSudo const & vecAttFractVol = avei.getVecFractManifElem();
    5617              : 
    5618              :                 for( AttachedFractFaceEdgeSudo const & affe : vecAttFractVol )
    5619              :                 {
    5620              :                         vecAttFractFaces.push_back(affe);
    5621              :                 }
    5622              :         }
    5623              : 
    5624              :         IndexType numbContrFracFaces = vecAttFractFaces.size();
    5625              : 
    5626              :         if( numbContrFracFaces < 1 )
    5627              :         {
    5628              :                 UG_LOG("Kein Affe da " << std::endl);
    5629              :                 UG_THROW("Kein Affe da " << std::endl);
    5630              :                 return false;
    5631              :         }
    5632              : 
    5633              :         IndexType sudoBase = vecAttFractFaces[0].getSudo();
    5634              : 
    5635              :         sudosInSegment.push_back(sudoBase);
    5636              : 
    5637              :         // add sudos different from the base one
    5638              :         for( AttachedFractFaceEdgeSudo const & affe : vecAttFractFaces )
    5639              :         {
    5640              :                 IndexType sudoNeeded = affe.getSudo();
    5641              : 
    5642              :                 bool sudoIsKnown = false;
    5643              : 
    5644              :                 for( IndexType sudoInList : sudosInSegment )
    5645              :                 {
    5646              :                         if( sudoNeeded == sudoInList )
    5647              :                         {
    5648              :                                 sudoIsKnown = true;
    5649              :                         }
    5650              :                 }
    5651              : 
    5652              :                 if( ! sudoIsKnown )
    5653              :                 {
    5654              :                         sudosInSegment.push_back(sudoNeeded);
    5655              :                 }
    5656              : 
    5657              :         }
    5658              : 
    5659              :         return true;
    5660              : }
    5661              : #endif
    5662              : 
    5663              : 
    5664              : ////////////////////////////////////////////////////////////////////
    5665              : // for only one surrounding subdom around the segment, for example only one fracture, or T End like ending side
    5666              : // TODO FIXME alles in eine einzige Funktion, die verschiedene Unterfunktionen aufruft für verschiedene Zahlen
    5667              : // von Seiten innen und aussen!!!!
    5668              : //template<>
    5669              : //bool ArteExpandFracs3D::expandWithinTheSegment<ArteExpandFracs3D::SegmentVrtxFracStatus::oneFracSuDoAtt>( SegmentLimitingSides const & segmLimSides )
    5670            0 : bool ArteExpandFracs3D::expandWithinTheSegment( ArteExpandFracs3D::SegmentLimitingSides & segmLimSides )
    5671              : {
    5672              :         // should not be called for boundary vertices
    5673              : 
    5674              :         bool isBndry = segmLimSides.isBoundary();
    5675              : 
    5676              : 
    5677              : //      if( isBndry )
    5678              : //              return true;
    5679              : 
    5680              : //      if( isBndry )
    5681              : //      {
    5682              : //              UG_LOG("boundary noch zu behandeln " << std::endl);
    5683              : //              UG_THROW("boundary noch zu behandeln " << std::endl);
    5684              : //              return false;
    5685              : //      }
    5686              : 
    5687              : //      VecSegmentLimitSidesPairSudoNorml vecSegmLimSidPrSudoNrml;
    5688              :         VecPlaneDescriptor vecPlaneFracDescr;
    5689              : 
    5690              :         //      if( ! segmLimSides.spuckFractSudoNormls( vecSegmLimSidPrSudoNrml ) )
    5691            0 :         if( ! segmLimSides.spuckFractManifDescr( vecPlaneFracDescr, m_aaPos ) )
    5692              :         {
    5693            0 :                 UG_LOG("Spucken schief gegangen  " << segmLimSides.spuckCrossingTyp() << std::endl);
    5694            0 :                 UG_THROW("Spucken schief gegangen  " << segmLimSides.spuckCrossingTyp() << std::endl);
    5695              :                 return false;
    5696              :         }
    5697              : 
    5698              :         // falls Boundary, hier noch spuckBndryManifDescr aufrufen
    5699              : 
    5700            0 :         Vertex * oldVrt = segmLimSides.spuckVertex();
    5701              :         vector3 posOldVrt = m_aaPos[oldVrt];
    5702              : 
    5703              :         VecPlaneDescriptor vecShiftedPlaneDescript;
    5704              : 
    5705              : //      for( SegmentLimitSidesPairSudoNorml const & segLimSidPrSN : vecSegmLimSidPrSudoNrml )
    5706            0 :         for( PlaneDescriptor & planeDescr : vecPlaneFracDescr )
    5707              :         {
    5708            0 :                 UG_LOG("GOT MANIF TYP " << planeDescr.spuckManifTyp() << std::endl );
    5709              : //              IndexType const & sudoSide = segLimSidPrSN.first;
    5710              : //              vector3 const & normlAvrg = segLimSidPrSN.second;
    5711              : //
    5712              : //              // normal computed standard mässig directs of of the volume, we need that one into the volume
    5713              : //              vector3 normalOutsideVol;
    5714              : 
    5715              :                 // hier testen, ob die Subdomain von der Liste der fracture subdomains ist,
    5716              :                 // damit für den Fall von sich zwei schneidenden Ebenen für die dritte,
    5717              :                 // die als senkrecht zu den beiden anderen gesetzt werden soll, mit Verschiebung null,
    5718              :                 // analog Boundary sides, die künstliche Weite null erhalten kann hier
    5719              : 
    5720            0 :                 if( planeDescr.spuckManifTyp() != PlaneDescriptorType::isFracture )
    5721            0 :                         UG_THROW("muss fracture sein " << std::endl);
    5722              : //
    5723              :                 int sudoSide = planeDescr.spuckSudo();
    5724            0 :                 number width = m_fracInfosBySubset[sudoSide].width;;
    5725              : 
    5726              :                 // ensure that the width is nonzero only for real fractures, not for pseudo vectors or such stuff
    5727              : //              if( ! isBndry )
    5728              : //              {
    5729              : //                      if( planeDescr.spuckManifTyp() == PlaneDescriptorType::isFracture )
    5730              : //                      {
    5731              : //                              width = m_fracInfosBySubset[sudoSide].width;
    5732              : //                      }
    5733              : //                      else
    5734              : //                      {
    5735              : //                              UG_LOG("Manif Typ is " << planeDescr.spuckManifTyp() << std::endl );
    5736              : //                              UG_LOG("Fract wäre " << PlaneDescriptorType::isFracture << std::endl );
    5737              : //                              UG_LOG("Bndry wäre " << PlaneDescriptorType:: << std::endl );
    5738              : //                              UG_LOG("Artif wäre " << PlaneDescriptorType::isArtificial << std::endl );
    5739              : //
    5740              : //                              UG_THROW("keine Boundary, aber will Boundary Manif" << std::endl);
    5741              : //                      }
    5742              : //              }
    5743              : //              else
    5744              : //              {
    5745              : //                      UG_THROW("hier nur keine boundary" << std::endl);
    5746              : //              }
    5747              : 
    5748              : 
    5749              : //              else
    5750              : //              {
    5751              : //      TODO FIXME              bei boundary auch noch für die entsprechenden boundaries
    5752              : //              }
    5753              : 
    5754            0 :                 number shiftScal = width / 2.;
    5755            0 :                 planeDescr.schluckScaleShiftNormal( - shiftScal );
    5756              : 
    5757              : //              vector3 shiftVec4Plane;
    5758              : //
    5759              : //              // as normal outside vol, but we need to go inside the volumes / segment side
    5760              : //              VecScale( shiftVec4Plane, normalOutsideVol, - shiftScal );
    5761              : 
    5762              : //              vecShiftVec4Plane.push_back( shiftVec4Plane );
    5763              : //              vecSudosSides.push_back( sudoSide );
    5764              : //              vecNormalsAveraged.push_back( normalIntoVol );
    5765              : 
    5766              : //              PlaneDescriptor planeDescr( normalOutsideVol, posOldVrt, shiftScal );
    5767              : 
    5768              :                 PlaneDescriptor shiftedPlaneDescr;
    5769            0 :                 planeDescr.spuckPlaneShifted( shiftedPlaneDescr );
    5770              : 
    5771              :                 //              planeDescr.spuckPlaneShiftedAlong( shiftVec4Plane, shiftedPlaneDescr );
    5772              : 
    5773            0 :                 vecShiftedPlaneDescript.push_back( shiftedPlaneDescr );
    5774              :         }
    5775              : 
    5776              :         // TODO FIXME test if the new points might squeeze the volumes
    5777              : 
    5778              : //      std::vector<Volume*> volsOfSegm;
    5779              : //
    5780              : //      if( ! segmLimSides.spuckListLowdimElmsOfVols( volsOfSegm, m_grid ) )
    5781              : //      {
    5782              : //              UG_LOG("which attached edges? " << std::endl);
    5783              : //              UG_LOG("which attached edges? " << std::endl);
    5784              : //      }
    5785              : 
    5786            0 :         bool testNewPoints = testIfNewPointsSqueezeVolumes( segmLimSides, vecShiftedPlaneDescript );
    5787              : 
    5788              :         UG_LOG("TESTING NEW POINTS IS " << testNewPoints << " of " << true << " or " << false << std::endl);
    5789              : 
    5790              : //      if( ! testIfNewPointsSqueezeVolumes( segmLimSides, vecShiftedPlaneDescript ) )
    5791            0 :         if( ! testNewPoints )
    5792              :         {
    5793              :                 UG_LOG("CAUTION: expansion probably violates the surrounding volumes!" << std::endl);
    5794              : //              return false;
    5795              :         }
    5796              : 
    5797              :         // will get the sudo of the shifted vertex
    5798              :         IndexType sudoExample = (vecPlaneFracDescr[0]).spuckSudo();
    5799              :         vector3 posNewVrt; // to be determined depending on the segment properties
    5800              : 
    5801              :         bool hasUnclosedFaces = segmLimSides.hasUnclosedFaces();
    5802              : 
    5803            0 :         if( hasUnclosedFaces )
    5804              :         {
    5805              :                 UG_LOG("hat ungeschlossene Seiten " << std::endl);
    5806              :         }
    5807              : 
    5808            0 :         if( ! isBndry && vecShiftedPlaneDescript.size() == 1 )
    5809              :         {
    5810              :                 // die unclosed crossing faces behandeln!!!
    5811              : 
    5812              :                 // muss wieder eingeschaltet werden hier
    5813              :                 // use the hasUnclosedFaces property, but for visual debugging, better set as false
    5814              :                 bool distinguishUnclosedFaces = segmLimSides.hasUnclosedFaces();
    5815              : //              constexpr bool distinguishUnclosedFaces = false; // segmLimSides.hasUnclosedFaces();
    5816              :                 UG_LOG("Please use switch unclosed faces in final version, please remove debugging set false" << std::endl);
    5817              : 
    5818            0 :                 if( ! distinguishUnclosedFaces ) // standard case, just shift perpendicular to the plane, no SLE to solve
    5819              :                 {
    5820              :                         //              // one single inner fracture, Testfall Anfang
    5821              :                         //              computeShiftVector( vecShiftedPlaneDescript[0] );
    5822            0 :                         posNewVrt = (vecPlaneFracDescr[0]).spuckShiftedBaseVect();
    5823              : 
    5824              :                 }
    5825              :                 else
    5826              :                 {
    5827              :                         // NOTE: TODO FIXME funktioniert vermutlich auch, wenn der Vertex ein Boundary Vertex ist
    5828              :                         // ob der Spezialfall aber auch praktisch vorkommt, fragwürdig
    5829              :                         // Test der Methode erstmal innen drin, später ggf. Ausweitung auf Grenzvertizes
    5830              :                         // dann würde das hier raus wandern aus dem Frage ob Boundary oder nicht, isBndry wäre egal
    5831              :                         // relevant wäre dass size des vecShiftPlaneDescr 1 ist und withUnclosedFaces true
    5832              : 
    5833              : 
    5834            0 :                         Edge * shiftDirectionEdg = nullptr;
    5835              : 
    5836              :                         if( ! segmLimSides.spuckLowdimElmShiftDirectionIfUnclosedFractPresent(shiftDirectionEdg) )
    5837              :                         {
    5838              :                                 UG_LOG("no shift direction " << std::endl);
    5839            0 :                                 UG_THROW("no shift direction " << std::endl);
    5840              : 
    5841              :                         }
    5842              : 
    5843              :                         if( shiftDirectionEdg == nullptr )
    5844              :                         {
    5845              :                                 UG_LOG("Null Shift cross end?" << std::endl);
    5846              :                                 UG_THROW("Null Shift cross end?" << std::endl);
    5847              :                         }
    5848              : 
    5849              :                         // jetzt sollte also die shift direction bekannt sein, muss normalisiert werden,
    5850              :                         // vielleicht kann man das im PlaneDescriptor drin auch machen
    5851              : 
    5852              :                         PlaneDescriptor const & shiftedPlane = vecShiftedPlaneDescript[0];
    5853              : 
    5854              : 
    5855            0 :                         if( ! computeCrossPointOfPlaneWithLine( shiftedPlane, shiftDirectionEdg, oldVrt, posNewVrt ) )
    5856              :                         {
    5857              :                                 UG_LOG("CAUTION: shifting cross point along ending crossing cleft edge might break volumes " << std::endl);
    5858              : 
    5859              : //                              UG_LOG("Not possible to compute crossing point plane with line" << std::endl);
    5860              : //                              UG_THROW("Not possible to compute crossing point plane with line" << std::endl);
    5861              :                         }
    5862              :                 }
    5863              :         }
    5864              :         else
    5865              :         {
    5866            0 :                 if( ! isBndry && vecShiftedPlaneDescript.size() > 1 )
    5867              :                 {
    5868              : 
    5869            0 :                         if( vecShiftedPlaneDescript.size() == 2 )
    5870              :                         {
    5871              :                                 // we need to add an artificial plane which gets extended with scale 0
    5872              : 
    5873              :                                 vector3 artificialNormal;
    5874            0 :                                 VecCross( artificialNormal, vecShiftedPlaneDescript[0].spuckNormalVector(), vecShiftedPlaneDescript[1].spuckNormalVector() );
    5875              : 
    5876            0 :                                 PlaneDescriptor artificialPlane( artificialNormal, posOldVrt );
    5877              : 
    5878            0 :                                 vecShiftedPlaneDescript.push_back(artificialPlane);
    5879              :                         }
    5880              : 
    5881            0 :                         if( vecShiftedPlaneDescript.size() > 3  )
    5882            0 :                                 UG_THROW("too much fractures" << std::endl);
    5883              : 
    5884              :                         // now we should have three planes to cross
    5885              : 
    5886              :                 }
    5887            0 :                 else if( isBndry )
    5888              :                 {
    5889              :                         VecPlaneDescriptor vecPlaneBndryDescr;
    5890              : 
    5891              :                         //      if( ! segmLimSides.spuckFractSudoNormls( vecSegmLimSidPrSudoNrml ) )
    5892            0 :                         if( ! segmLimSides.spuckBndryManifDescr( vecPlaneBndryDescr, m_aaPos ) )
    5893              :                         {
    5894            0 :                                 UG_LOG("Spucken schief gegangen bndry " << segmLimSides.spuckCrossingTyp() << std::endl);
    5895            0 :                                 UG_THROW("Spucken schief gegangen bndry " << segmLimSides.spuckCrossingTyp() << std::endl);
    5896              :                                 return false;
    5897              :                         }
    5898              : 
    5899            0 :                         if( vecPlaneBndryDescr.size() < 1 )
    5900              :                         {
    5901            0 :                                 UG_LOG("at point " << m_aaPos[oldVrt] << std::endl);
    5902              : 
    5903            0 :                                 UG_LOG("BOUNRARY PPPPP vertex BOUNDARY size problem " << m_aaPos[oldVrt] << std::endl);
    5904              : 
    5905              :                                 UG_LOG("Boundaries" << std::endl);
    5906            0 :                                 for( PlaneDescriptor pd : vecPlaneBndryDescr  )
    5907              :                                 {
    5908            0 :                                         UG_LOG("Subdom " << pd.spuckSudo() << std::endl);
    5909            0 :                                         UG_LOG("Base " << pd.spuckBaseVector() << std::endl);
    5910            0 :                                         UG_LOG("Normal " << pd.spuckNormalVector() <<std::endl);
    5911              :                                 }
    5912              : 
    5913              :                                 UG_LOG("Shifted" << std::endl);
    5914            0 :                                 for( PlaneDescriptor pd : vecShiftedPlaneDescript  )
    5915              :                                 {
    5916            0 :                                         UG_LOG("Subdom S " << pd.spuckSudo() << std::endl);
    5917            0 :                                         UG_LOG("Base S " << pd.spuckBaseVector() << std::endl);
    5918            0 :                                         UG_LOG("Normal S " << pd.spuckNormalVector() <<std::endl);
    5919              :                                 }
    5920              : 
    5921              :                                 UG_LOG("Fracs " << std::endl);
    5922            0 :                                 for( PlaneDescriptor pd : vecPlaneFracDescr  )
    5923              :                                 {
    5924            0 :                                         UG_LOG("Subdom F " << pd.spuckSudo() << std::endl);
    5925            0 :                                         UG_LOG("Base F " << pd.spuckBaseVector() << std::endl);
    5926            0 :                                         UG_LOG("Normal F " << pd.spuckNormalVector() <<std::endl);
    5927              :                                 }
    5928              : 
    5929              : 
    5930              :                                 // PROBLEM PPPPPPPPPPPPPPPPP
    5931            0 :                                 UG_THROW("NO boundary sudos " << std::endl);
    5932              :                         }
    5933              : 
    5934              :                         bool needToAverage = false;
    5935              : 
    5936            0 :                         if( vecPlaneBndryDescr.size() > 2 )
    5937              :                         {
    5938              : 
    5939              :                                 UG_LOG("dudos" << std::endl);
    5940            0 :                                 for( PlaneDescriptor pd : vecPlaneBndryDescr )
    5941              :                                 {
    5942              :                                         int sudo = pd.spuckSudo();
    5943            0 :                                         UG_LOG("sudos " << sudo << std::endl);
    5944              : 
    5945              :                                 }
    5946            0 :                                 UG_LOG("at point " << m_aaPos[oldVrt] << std::endl);
    5947              :                                 UG_LOG("too much boundary sudos - NEED TO AVERAGE OVER ALL - introduce pseudo boundary descriptor, size 1" << vecPlaneBndryDescr.size() << std::endl);
    5948              : 
    5949              :                                 needToAverage = true;
    5950              :                         }
    5951            0 :                         else if( vecPlaneBndryDescr.size() == 2 )
    5952              :                         {
    5953            0 :                                 if( vecPlaneFracDescr.size() == 2  )
    5954              :                                 {
    5955              :                                         UG_LOG("zwei Boundary subdoms plus zwei Kreuzungen " << std::endl);
    5956              :                                         needToAverage = true;
    5957              :                                 }
    5958              :                                 else
    5959              :                                 {
    5960              :                                         // depending on angle between the two boundary normals, an averaging also useful, if too similar
    5961              : 
    5962              :                                         vector3 const & normalOne = vecPlaneBndryDescr[0].spuckNormalVector();
    5963              :                                         vector3 const & normalTwo = vecPlaneBndryDescr[1].spuckNormalVector();
    5964              : 
    5965              :                                         number lengthOne = VecLength(normalOne);
    5966              :                                         number lengthTwo = VecLength(normalTwo);
    5967              : 
    5968              :                                         vector3 crossVec;
    5969              : 
    5970            0 :                                         VecCross(crossVec, normalOne, normalTwo);
    5971              : 
    5972              :                                         number crossProdBetween = VecLength(crossVec);
    5973              : 
    5974              :                                         number tol = 1e-1;
    5975              : 
    5976            0 :                                         number deviationOne = std::fabs( (lengthOne - 1.) / (lengthOne + 1 ) );
    5977            0 :                                         number deviationTwo = std::fabs( (lengthTwo - 1.) / (lengthTwo + 1 ) );
    5978              : 
    5979            0 :                                         if( deviationOne > tol || deviationTwo > tol )
    5980              :                                         {
    5981            0 :                                                 UG_LOG("Normals no length one " << normalOne << " " << normalTwo << std::endl);
    5982            0 :                                                 UG_THROW("Normals no length one " << normalOne << " " << normalTwo << std::endl);
    5983              :                                         }
    5984              : 
    5985            0 :                                         number sinBetween = std::fabs( crossProdBetween / lengthOne / lengthTwo );
    5986              : 
    5987              :                                         number decisionSin = 0.05;
    5988              : 
    5989            0 :                                         if( decisionSin > sinBetween )
    5990              :                                         {
    5991              :                                                 needToAverage = true;
    5992              : //                                              m_sh.assign_subset(oldVrt, m_sh.num_subsets());
    5993              : //                                              return false;
    5994              : 
    5995              :                                         }
    5996              : 
    5997              :                                         // very close, so better average, as they might be even parallel
    5998              :                                 }
    5999              :                         }
    6000              : 
    6001              : 
    6002              : 
    6003              :                         if( ! needToAverage  )
    6004              :                         {
    6005              : 
    6006            0 :                                 if( vecShiftedPlaneDescript.size() + vecPlaneBndryDescr.size() > 3 )
    6007            0 :                                         UG_THROW("too much crossing stuff at boundary"<<std::endl);
    6008              : 
    6009            0 :                                 for( PlaneDescriptor const & pbd : vecPlaneBndryDescr )
    6010              :                                 {
    6011            0 :                                         vecShiftedPlaneDescript.push_back( pbd );
    6012              :                                 }
    6013              : 
    6014            0 :                                 if( vecPlaneBndryDescr.size() == 2 )
    6015              :                                 {
    6016              :                                         // PROBLEM PPPPPPPPPPPPPPPP
    6017            0 :                                         if( vecShiftedPlaneDescript.size() != 3 ||  vecPlaneFracDescr.size() != 1 )
    6018              :                                         {
    6019            0 :                                                 UG_LOG("BOUNRARY PPPPP vertex TWO problem " << m_aaPos[oldVrt] << std::endl);
    6020              : 
    6021              :                                                 UG_LOG("Boundaries" << std::endl);
    6022            0 :                                                 for( PlaneDescriptor pd : vecPlaneBndryDescr  )
    6023              :                                                 {
    6024            0 :                                                         UG_LOG("Subdom " << pd.spuckSudo() << std::endl);
    6025            0 :                                                         UG_LOG("Base " << pd.spuckBaseVector() << std::endl);
    6026            0 :                                                         UG_LOG("Normal " << pd.spuckNormalVector() <<std::endl);
    6027              :                                                 }
    6028              : 
    6029              :                                                 UG_LOG("Shifted" << std::endl);
    6030            0 :                                                 for( PlaneDescriptor pd : vecShiftedPlaneDescript  )
    6031              :                                                 {
    6032            0 :                                                         UG_LOG("Subdom S " << pd.spuckSudo() << std::endl);
    6033            0 :                                                         UG_LOG("Base S " << pd.spuckBaseVector() << std::endl);
    6034            0 :                                                         UG_LOG("Normal S " << pd.spuckNormalVector() <<std::endl);
    6035              :                                                 }
    6036              : 
    6037              :                                                 UG_LOG("Fracs " << std::endl);
    6038            0 :                                                 for( PlaneDescriptor pd : vecPlaneFracDescr  )
    6039              :                                                 {
    6040            0 :                                                         UG_LOG("Subdom F " << pd.spuckSudo() << std::endl);
    6041            0 :                                                         UG_LOG("Base F " << pd.spuckBaseVector() << std::endl);
    6042            0 :                                                         UG_LOG("Normal F " << pd.spuckNormalVector() <<std::endl);
    6043              :                                                 }
    6044              : 
    6045            0 :                                                 UG_THROW("noch nicht genug Grenzen " << std::endl);
    6046              : 
    6047              :                                         }
    6048              :                                 }
    6049            0 :                                 else if( vecPlaneBndryDescr.size() == 1 )
    6050              :                                 {
    6051            0 :                                         if( vecShiftedPlaneDescript.size() < 3 )
    6052              :                                                 UG_LOG("noch nicht genug Grenzen " << std::endl);
    6053              : 
    6054            0 :                                         if( vecShiftedPlaneDescript.size() > 3 )
    6055              :                                                 UG_LOG("too much Grenzen " << std::endl);
    6056              : 
    6057            0 :                                         if( vecPlaneFracDescr.size() != 1 && vecPlaneFracDescr.size() != 2 )
    6058            0 :                                                 UG_THROW("Nicht passend Fract plus Bndry" << std::endl);
    6059              : 
    6060              :         //                              if( vecPlaneFracDescr.size() == 1 && vecPlaneFracDescr.size() == 2 )
    6061              :         //                                      if( vecShiftedPlaneDescript.size() != 3 )
    6062              :         //                                              UG_THROW"SO viele unsinnige Kombinationen " << std::endl );
    6063              : 
    6064            0 :                                         if( vecPlaneFracDescr.size() == 2 )
    6065              :                                         {
    6066            0 :                                                 if( vecShiftedPlaneDescript.size() != 3 )
    6067            0 :                                                         UG_THROW("da passt nicht zusammen was 3 sein sollte" << std::endl);
    6068              : 
    6069              :                                                 // sonst nix zu tun
    6070              :                                         }
    6071              :                                         else if( vecPlaneFracDescr.size() == 1 )
    6072              :                                         {
    6073            0 :                                                 if( vecShiftedPlaneDescript.size() != 2 )
    6074              :                                                         UG_LOG("1+2 nicht 3" << std::endl);
    6075              : 
    6076              :                                                 // add an artificial perpendicular plane with move vector zero
    6077              : 
    6078              :                                                 vector3 artificialNormal;
    6079            0 :                                                 VecCross( artificialNormal, vecShiftedPlaneDescript[0].spuckNormalVector(), vecShiftedPlaneDescript[1].spuckNormalVector() );
    6080              : 
    6081            0 :                                                 PlaneDescriptor artificialPlane( artificialNormal, posOldVrt );
    6082              : 
    6083            0 :                                                 vecShiftedPlaneDescript.push_back(artificialPlane);
    6084              : 
    6085              :                                         }
    6086              : 
    6087              : 
    6088              : 
    6089              :                                 }
    6090              : 
    6091              :                         }
    6092              :                         else
    6093              :                         {
    6094              :                                 // need to average boundaries
    6095              : 
    6096              :                                 // AVERAGE in this case and introduce an averaged pseudo boundary descriptor
    6097              :                                 // AAAAAAAAAAAAAAAA
    6098              : 
    6099              :                                 vector3 averagedNormal;
    6100              : 
    6101              : //                              if( ! averageBndryNormals( VecPlaneDescriptor const & vecPlaneBndryDescr, vector3 & averagedNormal ) )
    6102            0 :                                 if( ! averageBndryNormals( vecPlaneBndryDescr, averagedNormal ) )
    6103              :                                 {
    6104              :                                         UG_LOG("NORMAL NOT AVERAGABLE" << std::endl);
    6105            0 :                                         UG_THROW("NORMAL NOT AVERAGABLE" << std::endl);
    6106              :                                         return false;
    6107              :                                 }
    6108              : 
    6109            0 :                                 PlaneDescriptor averagedBoundaryPlane( averagedNormal, posOldVrt );
    6110            0 :                                 vecShiftedPlaneDescript.push_back(averagedBoundaryPlane);
    6111              : 
    6112            0 :                                 if( vecPlaneFracDescr.size() == 1 )
    6113              :                                 {
    6114              :                                         // behave as if we would have one boundary and thus need one additional artificial normal
    6115              : 
    6116              :                                         vector3 artificialNormal;
    6117            0 :                                         VecCross( artificialNormal, vecShiftedPlaneDescript[0].spuckNormalVector(), averagedNormal );
    6118              : 
    6119            0 :                                         PlaneDescriptor artificialPlane( artificialNormal, posOldVrt );
    6120              : 
    6121            0 :                                         vecShiftedPlaneDescript.push_back(artificialPlane);
    6122              :                                 }
    6123              : 
    6124              :                         }
    6125              : 
    6126              : 
    6127            0 :                 }
    6128              : 
    6129              :                 // vector shifted plane descriptor kriegt was dazu, wenn es keine drei sind ohne boundary
    6130              : 
    6131            0 :                 if( vecShiftedPlaneDescript.size() != 3 )
    6132            0 :                         UG_THROW("wie gross soll es denn sein" << std::endl);
    6133              : 
    6134            0 :                 computeCrossingPointOf3Planes( vecShiftedPlaneDescript, posNewVrt );
    6135              : 
    6136              :         }
    6137              : 
    6138              : 
    6139              : 
    6140              : //      if( vecSegmLimSidPrSudoNrml.size() != 1 )
    6141              : //      {
    6142              : //              UG_LOG("only one fracture, but not one normal and sudo?"  <<  std::endl);
    6143              : //              UG_THROW("only one fracture, but not one normal and sudo?" << std::endl);
    6144              : //              return false;
    6145              : //      }
    6146              : 
    6147              :         // FALL eins extra Funktion, unterscheiden nach Länge
    6148              : 
    6149              : //      if(  )
    6150              : 
    6151              : 
    6152              : //      SegmentLimitSidesPairSudoNorml & sudoAndNormal = vecSegmLimSidPrSudoNrml[0];
    6153              : //
    6154              : //      IndexType sudoBase = sudoAndNormal.first;
    6155              : //      vector3 normalsAveraged = sudoAndNormal.second;
    6156              : //
    6157              : //      Vertex * oldVrt = segmLimSides.spuckVertex();
    6158              : //
    6159              : //      number width = m_fracInfosBySubset[sudoBase].width;
    6160              : //
    6161              : //      number scal = width / 2.;
    6162              : //
    6163              : //      NormalVectorFacIntoVol scaledNormal;
    6164              : //
    6165              : //      VecScale( scaledNormal, normalsAveraged, - scal );
    6166              : //
    6167              : //      vector3 posOldVrt = m_aaPos[oldVrt];
    6168              : //
    6169              : //      UG_LOG("NORMAL OLD VRTX " << posOldVrt << " -> " << normalsAveraged << std::endl );
    6170              : 
    6171              : 
    6172              : //      VecAdd( posNewVrt, posOldVrt, scaledNormal );
    6173              : 
    6174            0 :         Vertex * newShiftVrtx = *m_grid.create<RegularVertex>();
    6175              : 
    6176            0 :         if( newShiftVrtx == nullptr )
    6177              :         {
    6178              :                 UG_LOG("Nullen erzeugt" << std::endl);
    6179            0 :                 UG_THROW("Nullen erzeugt" << std::endl);
    6180              :                 return false;
    6181              :         }
    6182              : 
    6183              :         m_aaPos[newShiftVrtx] = posNewVrt;
    6184              : 
    6185            0 :         UG_LOG("Created new vertex at " << m_aaPos[newShiftVrtx] << std::endl );
    6186              : 
    6187            0 :         m_sh.assign_subset(newShiftVrtx, sudoExample);
    6188              : //      m_sh.assign_subset(newShiftVrtx, m_sh.num_subsets());
    6189              : 
    6190              :         // wenn der neue Vertex mit einer ungeschlossenen endenden Kluft zu tun hat
    6191              :         // muss am Ende vom Kernvertex, old vertex, die edge, die nicht mit der
    6192              :         // kreuzenden nicht endenden KLuft geht, gelöscht werden
    6193              :         m_vrtxAttAccsVrtxArisesFromExpandedEndingCrossingCleft[newShiftVrtx] = hasUnclosedFaces;
    6194              : 
    6195              :         // TODO FIXME das auch verwenden
    6196              : 
    6197            0 :         if( hasUnclosedFaces )
    6198              :         {
    6199              :                 // TEST AUF ANZAHL der kreuzenden Klüfte, zusätzlich, ob es eine ist nur
    6200              :                 // zur Sicherheit
    6201            0 :                 if( isBndry || vecShiftedPlaneDescript.size() != 1 )
    6202              :                 {
    6203              :                         UG_LOG("Shift vertex but boundary or more than one shift direction " << std::endl);
    6204            0 :                         UG_THROW("Shift vertex but boundary or more than one shift direction " << std::endl);
    6205              :                 }
    6206              : 
    6207            0 :                 if( ! addElem( m_vrtxArisesFromExpandedEndingCrossingCleft, newShiftVrtx ) )
    6208              :                 {
    6209              :                         UG_LOG("Shifted ecf vertex schon bekannt " << std::endl);
    6210            0 :                         UG_THROW("Shifted ecf vertex schon bekannt " << std::endl);
    6211              :                 }
    6212              : 
    6213              :                 // TODO FIXME figure out segment limiting side of the member vector and add the shift vertex
    6214              : 
    6215              :                 Edge * shiftDirection = nullptr;
    6216              : 
    6217            0 :                 if( ! segmLimSides.spuckLowdimElmShiftDirectionIfUnclosedFractPresent( shiftDirection ) )
    6218              :                 {
    6219              :                         UG_LOG("No shift direction in ending crossing cleft segment " << std::endl);
    6220            0 :                         UG_THROW("No shift direction in ending crossing cleft segment " << std::endl);
    6221              :                 }
    6222              : 
    6223              :                 IndexType numFoundECFSI = 0;
    6224              : 
    6225              :                 // figure out the Ending crossing cleft segment info corresponding to this shift edge
    6226            0 :                 for( EndingCrossingFractureSegmentInfo const & ecfs : m_vecEndCrossFractSegmInfo )
    6227              :                 {
    6228            0 :                         if( ecfs.spuckLowdimElmShiftDirection() == shiftDirection )
    6229            0 :                                 numFoundECFSI++;
    6230              :                 }
    6231              : 
    6232            0 :                 if( numFoundECFSI != 1 )
    6233              :                 {
    6234              :                         UG_LOG("not one cefsi found " << numFoundECFSI << std::endl);
    6235            0 :                         UG_THROW("not one cefsi found " << numFoundECFSI << std::endl);
    6236              :                 }
    6237              : 
    6238            0 :                 for( EndingCrossingFractureSegmentInfo & ecfs : m_vecEndCrossFractSegmInfo )
    6239              :                 {
    6240            0 :                         if( ecfs.spuckLowdimElmShiftDirection() == shiftDirection )
    6241              :                         {
    6242            0 :                                 if( ! ecfs.schluckShiftVrtx( newShiftVrtx ) )
    6243              :                                 {
    6244            0 :                                         UG_LOG("Shift vertex wird nicht geschluckt" << m_aaPos[newShiftVrtx] << std::endl );
    6245            0 :                                         UG_THROW("Shift vertex wird nicht geschluckt" << m_aaPos[newShiftVrtx] << std::endl );
    6246              :                                         return false;
    6247              :                                 }
    6248              : 
    6249              :                                 break;
    6250              :                         }
    6251              :                 }
    6252              : 
    6253              :                 IndexType numFoundAssigned = 0;
    6254              : 
    6255            0 :                 for( EndingCrossingFractureSegmentInfo const & ecfs : m_vecEndCrossFractSegmInfo )
    6256              :                 {
    6257            0 :                         if( ecfs.spuckShiftVrtx() != nullptr && ecfs.spuckLowdimElmShiftDirection() == shiftDirection )
    6258            0 :                                 numFoundAssigned++;
    6259              :                 }
    6260              : 
    6261            0 :                 if( numFoundAssigned != 1 )
    6262              :                 {
    6263            0 :                         m_sh.assign_subset( oldVrt, m_sh.num_subsets());
    6264            0 :                         m_sh.assign_subset( shiftDirection, m_sh.num_subsets());
    6265              : 
    6266              : 
    6267              :                         UG_LOG( "num found assigend wrong " << numFoundAssigned );
    6268            0 :                         UG_THROW( "num found assigend wrong " << numFoundAssigned );
    6269              :                 }
    6270              : 
    6271              :                 UG_LOG("ending crossing cleft shift vertex generated " << std::endl);
    6272              : 
    6273              :         }
    6274              : 
    6275              :         std::vector<Volume*> volsInSegm;
    6276              : 
    6277              :         segmLimSides.spuckVecFulldimElem( volsInSegm );
    6278              : 
    6279            0 :         for( Volume * const & vol : volsInSegm )
    6280              :         {
    6281            0 :                 std::vector<Vertex*> & newVrts4Fac = m_aaVrtVecVol[ vol ];
    6282              : 
    6283            0 :                 for(size_t indVrt = 0; indVrt < (vol)->num_vertices();  indVrt++ )
    6284              :                 {
    6285            0 :                         Vertex* volVrt = (vol)->vertex(indVrt);
    6286              : 
    6287            0 :                         if(  volVrt == oldVrt )
    6288              :                         {
    6289            0 :                                 newVrts4Fac[ indVrt ] = newShiftVrtx;
    6290              :                         }
    6291              :                 }
    6292              :         }
    6293              : 
    6294              : //      if( isCrossingPt )
    6295              : //      {
    6296              : //              VrtxPair oldNewV( oldVrt, newShiftVrtx );
    6297              : //              m_oldNewVrtcs4Diams.push_back(oldNewV);
    6298              : //      }
    6299              : 
    6300              : 
    6301              : 
    6302              :         return true;
    6303              : 
    6304              : 
    6305            0 : }
    6306              : 
    6307              : //////////////////////////////////////////////////////////////////////////
    6308              : 
    6309              : 
    6310            0 : bool ArteExpandFracs3D::averageBndryNormals( VecPlaneDescriptor const & vecPlaneBndryDescr, vector3 & averagedNormal  )
    6311              : {
    6312            0 :         if( vecPlaneBndryDescr.size() == 0 )
    6313              :         {
    6314              :                 UG_LOG("no boundary" << std::endl);
    6315            0 :                 return false;
    6316              :         }
    6317              : 
    6318              :         vector3 normalsSum;
    6319              : 
    6320            0 :         for( PlaneDescriptor const & pd : vecPlaneBndryDescr )
    6321              :         {
    6322              :                 vector3 const & norml = pd.spuckNormalVector();
    6323              : 
    6324              :                 vector3 normalsSumBefore = normalsSum;
    6325              : 
    6326              :                 VecAdd(normalsSum, norml, normalsSumBefore );
    6327              :         }
    6328              : 
    6329            0 :         VecScale( averagedNormal, normalsSum, static_cast<number>(vecPlaneBndryDescr.size()) );
    6330              : 
    6331              :         return true;
    6332              : 
    6333              : }
    6334              : 
    6335              : 
    6336              : ///////////////////////////////////////////////////////////////////////////
    6337              : 
    6338            0 : bool ArteExpandFracs3D::testIfNewPointsSqueezeVolumes( ArteExpandFracs3D::SegmentLimitingSides & segmLimSides,
    6339              :                 ArteExpandFracs3D::VecPlaneDescriptor const & vecShiftedPlaneDescript )
    6340              : {
    6341              :         // TODO FIXME test if the new points might squeeze the volumes
    6342              : 
    6343              :         UG_LOG("TEST POINTS BEGIN " << std::endl);
    6344              : 
    6345              :         bool notViolated = true;
    6346              : 
    6347            0 :         IndexType debugSubs = m_sh.num_subsets();
    6348              : 
    6349            0 :         Vertex * oldVrt = segmLimSides.spuckVertex();
    6350              :         vector3 posOldVrt = m_aaPos[oldVrt];
    6351              : 
    6352              :         vector3 posTestVertex;
    6353              : 
    6354              :         std::vector<Edge*> vecEdgesOfSegVols;
    6355              : 
    6356            0 :         if( ! segmLimSides.spuckListLowdimElmsOfVols( vecEdgesOfSegVols, m_grid ) )
    6357              :         {
    6358              :                 UG_LOG("which attached edges? " << std::endl);
    6359              :                 UG_LOG("which attached edges? " << std::endl);
    6360              :         }
    6361              : 
    6362            0 :         if( vecEdgesOfSegVols.size() == 0 )
    6363              :         {
    6364              :                 UG_LOG("NO EDGES" << std::endl);
    6365              :         }
    6366              : 
    6367              :         std::vector<Volume*> attVols;
    6368              : 
    6369              :         segmLimSides.spuckVecFulldimElem(attVols);
    6370              : 
    6371            0 :         if( attVols.size() == 0 )
    6372              :         {
    6373              :                 UG_LOG("NO VOLS " << std::endl);
    6374              :         }
    6375              : 
    6376              :         UG_LOG("TEST POINTS MIDDLE " << notViolated << std::endl);
    6377              : 
    6378              : 
    6379            0 :         for( PlaneDescriptor const & shiftedPlane : vecShiftedPlaneDescript )
    6380              :         {
    6381              :                 std::vector<Edge *> manifoldEdges;
    6382              : 
    6383            0 :                 if( ! shiftedPlane.spuckLowDimElms(manifoldEdges) )
    6384              :                 {
    6385              :                         UG_LOG("NO MANIFOLD EDGED OF PLANE " << std::endl);
    6386            0 :                         UG_THROW("NO MANIFOLD EDGED OF PLANE " << std::endl);
    6387              :                 }
    6388              : 
    6389              :                 // TODO FIXME nur die Edges, die NICHT zur Basis-Ebene gehören, die, die zur Mannigfaltigkeit
    6390              :                 // gehören, die expandiert wird, müssen raus gefiltert werden!!!!!
    6391            0 :                 for( Edge * testEdge : vecEdgesOfSegVols )
    6392              :                 {
    6393              : //                      if( ! testEdge )
    6394              : //                              continue;
    6395              : 
    6396              :                         // test if testEdge belongs to the allowed Edges
    6397              : 
    6398              :                         bool isManifEdg = false;
    6399              : 
    6400            0 :                         for( Edge * me : manifoldEdges )
    6401              :                         {
    6402            0 :                                 if( me == testEdge )
    6403              :                                 {
    6404              :                                         isManifEdg = true;
    6405              :                                         UG_LOG("Test edge is manifold edge" << std::endl);
    6406            0 :                                         continue;
    6407              :                                 }
    6408              : 
    6409              :                                 // if edge belongs to manifold, it must not be considered!!!
    6410              :                         }
    6411              : 
    6412            0 :                         if( isManifEdg )
    6413            0 :                                 continue;
    6414              : 
    6415              :                         UG_LOG("TESTING CROSS POINT " << notViolated << std::endl);
    6416              : 
    6417              :                         // abuse of the compute cross point function originally developped for ending crossing cleft purposes
    6418            0 :                         if( ! computeCrossPointOfPlaneWithLine( shiftedPlane, testEdge, oldVrt, posTestVertex ) )
    6419              :                         {
    6420              :                                 UG_LOG("CAUTION: shifting cross point along test procedure cleft edge might break volumes " << std::endl);
    6421              : 
    6422              :                                 notViolated = false;
    6423              : 
    6424              :                                 UG_LOG("DEBUGGING WITH SUDO " << debugSubs << std::endl );
    6425              : 
    6426              : //                              return false;
    6427              : 
    6428            0 :                                 for( IndexType i = 0; i < 2; i++ )
    6429              :                                 {
    6430            0 :                                         Vertex * testVertex = testEdge->vertex(i);
    6431              : 
    6432            0 :                                         if( testVertex != oldVrt )
    6433              :                                         {
    6434            0 :                                                 addElem( m_vrtcsViolatingExpansion, testVertex );
    6435              :                                                 break;
    6436              :                                         }
    6437              :                                 }
    6438              : 
    6439            0 :                                 for( Volume * vol : attVols )
    6440              :                                 {
    6441            0 :                                         if( VolumeContains( vol, testEdge ))
    6442              :                                         {
    6443            0 :                                                 addElem(m_volsViolatingExpansion, vol);
    6444            0 :                                                 m_sh.assign_subset( vol, debugSubs );
    6445            0 :                                                 UG_LOG("CAUTION quenched volume, assigning debug subset " << debugSubs
    6446              :                                                                 << " for vol with center " << CalculateCenter( vol, m_aaPos )
    6447              :                                                                 << " for fracture subdomain " << shiftedPlane.spuckSudo() << std::endl);
    6448              :                                         }
    6449              :                                 }
    6450              : 
    6451              :                         }
    6452              : 
    6453              :                 }
    6454              : 
    6455            0 :         }
    6456              : 
    6457              :         UG_LOG("TEST POINTS END " << notViolated << " of " << true << " " << false << std::endl);
    6458              : 
    6459              : 
    6460            0 :         return true;
    6461              : 
    6462            0 : }
    6463              : 
    6464              : //////////////////////////////////////////////////////////////////////////
    6465              : 
    6466              : 
    6467            0 : bool ArteExpandFracs3D::computeCrossPointOfPlaneWithLine( PlaneDescriptor const & shiftedPlane, Edge * const & shiftDirectionEdg, Vertex * const & oldVrt, vector3 & posCrossingPt )
    6468              : {
    6469              :         UG_LOG("computing cross point start " << std::endl);
    6470              : 
    6471              :         vector3 const & normalShiftedPlane = shiftedPlane.spuckNormalVector();
    6472              :         vector3 const & baseShiftedPlane = shiftedPlane.spuckBaseVector();
    6473              :         number const & rhs = shiftedPlane.spuckRHS();
    6474              : 
    6475              :         // vector3 posOldVrt Aufpunkt der Edge, entland der verschoben werden soll
    6476              :         // establish
    6477              : 
    6478            0 :         if( ! ( EdgeContains(shiftDirectionEdg, oldVrt ) ) )
    6479              :         {
    6480              :                 UG_LOG("Shift edge ohne alten Vertex?" << std::endl);
    6481            0 :                 UG_THROW("Shift edge ohne alten Vertex?" << std::endl);
    6482              :         }
    6483              : 
    6484            0 :         vector3 posOldVrt = m_aaPos[oldVrt];
    6485              : 
    6486            0 :         UG_LOG("Pos old vertex CCP " << posOldVrt << std::endl);
    6487              : 
    6488              :         vector3 const & shiftVecBase = posOldVrt;
    6489              : 
    6490            0 :         Vertex * const & shiftEdgeVrtOne = shiftDirectionEdg->vertex(0);
    6491            0 :         Vertex * const & shiftEdgeVrtTwo = shiftDirectionEdg->vertex(1);
    6492              : 
    6493              :         vector3 shiftVecEnd = shiftVecBase; // needs to be changed still
    6494              : 
    6495            0 :         if( shiftEdgeVrtOne == oldVrt )
    6496              :         {
    6497              :                 shiftVecEnd = m_aaPos[shiftEdgeVrtTwo];
    6498              :         }
    6499            0 :         else if( shiftEdgeVrtTwo == oldVrt )
    6500              :         {
    6501              :                 shiftVecEnd = m_aaPos[shiftEdgeVrtOne];
    6502              :         }
    6503              :         else
    6504              :         {
    6505              :                 UG_LOG("no end vertex" << std::endl);
    6506            0 :                 UG_THROW("no end vertex" << std::endl);
    6507              :         }
    6508              : 
    6509              :         vector3 directionVec;
    6510              : 
    6511              :         VecSubtract(directionVec, shiftVecEnd, posOldVrt );
    6512              : 
    6513            0 :         UG_LOG("SHIVEEND " << shiftVecEnd << std::endl);
    6514            0 :         UG_LOG("POS OLD " << posOldVrt << std::endl);
    6515              : 
    6516              : 
    6517              :         // x = aufpunkt + s . r
    6518              :         // richtung einsetzen in ( x - x_0 ) * n = 0, auflösen nach s
    6519              :         // . gilt als Skalarprodukt, * als Kreuzprodukt hier in Notation
    6520              :         // x*n = rhs = x_0*n
    6521              :         // ( a + s . r -x0 ) * n = 0
    6522              :         // a * n + s . n * r - x0*n = 0
    6523              :         // s . ( n * r ) = x0 * n - a * n
    6524              :         // "Normallfall": n*r != 0
    6525              :         // dann gilt
    6526              :         // s = ( x0*n - a*n ) / ( n*r )
    6527              :         // Spezialfall: n*r = 0 dann, wenn Richtungsvektor Gerade und Normalenvektor Ebene übereinstimmen
    6528              :         // also wenn Verschiebung entlang der Normalen
    6529              :         // dann ist (x0-a) parallel zu n bzw r, dann ist die Frage, was für ein Vielfaches von r ist (x0-a)
    6530              :         // also a + s . r - x0 = 0 auflösen nach s
    6531              :         // s . r = x0 - a , muss auch für den Betrag gelten
    6532              :         // also s | r | = | x_0 - a |
    6533              :         // also s = | x_0 - a | / | r |
    6534              : 
    6535              :         number planeBaseMultNormal = VecDot(baseShiftedPlane,normalShiftedPlane);
    6536              :         number lineBaseMultNormal = VecDot(posOldVrt,normalShiftedPlane);
    6537              :         number lineDirMultNormal = VecDot( directionVec, normalShiftedPlane );
    6538              : 
    6539            0 :         UG_LOG("base shift plane " << baseShiftedPlane << std::endl);
    6540            0 :         UG_LOG("normal shift plane " << normalShiftedPlane << std::endl);
    6541            0 :         UG_LOG("pos Old " << posOldVrt << std::endl);
    6542            0 :         UG_LOG("direction " << directionVec << std::endl);
    6543              : 
    6544              : 
    6545            0 :         UG_LOG("COMPARE RHS AND LBMN " << rhs << " - " << planeBaseMultNormal << std::endl);
    6546              : 
    6547            0 :         number fbs = std::fabs( ( rhs - planeBaseMultNormal ) / ( rhs + planeBaseMultNormal) );
    6548              : 
    6549              :         UG_LOG("RELATIVE DIFF " << fbs << std::endl);
    6550              : 
    6551              :         number const d_toler = 1e-4;
    6552              : 
    6553            0 :         if( fbs > d_toler )
    6554              :         {
    6555              :                 UG_LOG("RELATIVE DIFF TOO BIG " << std::endl);
    6556            0 :                 UG_THROW("RELATIVE DIFF TOO BIG " << std::endl);
    6557              :         }
    6558              : 
    6559              :         number moveAlongLine = 0;
    6560              : 
    6561            0 :         if( lineDirMultNormal == 0. )
    6562              :         {
    6563              :                 UG_LOG("SHIFT denominator zero division " << std::endl);
    6564              : //              UG_THROW("denominator zero division " << std::endl);
    6565              : 
    6566              :                 vector3 connectNewAndOldBase;
    6567              :                 VecSubtract(connectNewAndOldBase, baseShiftedPlane, posOldVrt );
    6568              : 
    6569              :                 // Test also if the connection vector parallel to normalShiftedPlane and directionVec
    6570              : 
    6571              :                 number testParallShiftPlan = std::fabs( VecDot( connectNewAndOldBase, normalShiftedPlane ) );
    6572            0 :                 number testParallDirVec = std::fabs( VecDot( connectNewAndOldBase, directionVec ) );
    6573              : 
    6574            0 :                 if( testParallDirVec > d_toler || testParallDirVec > d_toler )
    6575              :                 {
    6576              :                         UG_LOG("VECTORS PARALLEL AND NOT " << std::endl);
    6577            0 :                         UG_THROW("VECTORS PARALLEL AND NOT " << std::endl);
    6578              :                 }
    6579              : 
    6580              :                 number lengthDirVec = VecLength(directionVec);
    6581              :                 number lengthConnVec = VecLength(connectNewAndOldBase);
    6582              : 
    6583            0 :                 moveAlongLine = lengthConnVec / lengthDirVec;
    6584              : 
    6585              :                 UG_LOG("MONULL " << lengthConnVec << " " << lengthDirVec << std::endl );
    6586              :         }
    6587              :         else
    6588              :         {
    6589            0 :                 moveAlongLine = ( planeBaseMultNormal - lineBaseMultNormal ) / lineDirMultNormal;
    6590              : 
    6591              :                 UG_LOG("MOAL  " << planeBaseMultNormal << " " <<  lineBaseMultNormal << " " <<  lineDirMultNormal << std::endl );
    6592              :         }
    6593              : 
    6594            0 :         if( moveAlongLine == 0. )
    6595              :         {
    6596              :                 UG_LOG("No Moving?" << std::endl);
    6597            0 :                 UG_THROW("No Moving?" << std::endl);
    6598              :         }
    6599              : 
    6600              :         vector3 shiftAlongLine;
    6601              : 
    6602              :         VecScale( shiftAlongLine, directionVec, moveAlongLine );
    6603              : 
    6604            0 :         UG_LOG("SHIFT " << shiftAlongLine << " Dir " << directionVec << " MOV " << moveAlongLine << std::endl );
    6605              : 
    6606              :         VecAdd( posCrossingPt, posOldVrt, shiftAlongLine );
    6607              : 
    6608              : //      m_allowedSqueeze = 0.8;
    6609              : 
    6610              : //      UG_LOG("MOVING " << moveAlongLine << std::endl);
    6611              : 
    6612              :         // falsch bei ending crossing cleft Verschiebung u.U. , zweiten Parameter dazu zur Unterscheidung?
    6613              :         // Vertex erzeugen wenn Problem an der Stelle? um zu sehen, wo es hin will?
    6614            0 :         if( moveAlongLine > m_allowedSqueeze )
    6615              :         {
    6616            0 :                 UG_LOG("MOVING ALONG LINE TOO BIG C " << posCrossingPt << " Old " << posOldVrt << " move " << shiftAlongLine << std::endl);
    6617              : 
    6618              :                 // create debug vertex at position of crossing point
    6619              : 
    6620            0 :                 Vertex * dbgVrtx = *m_grid.create<RegularVertex>();
    6621              : 
    6622              :                 m_aaPos[dbgVrtx] = posCrossingPt;
    6623              : 
    6624            0 :                 IndexType strangeSubs = m_sh.num_subsets();
    6625              : 
    6626            0 :                 m_sh.assign_subset(dbgVrtx, strangeSubs);
    6627              : 
    6628            0 :                 m_sh.assign_subset( shiftDirectionEdg, strangeSubs );
    6629              : //              m_sh.assign_subset( shiftDirectionEdg, m_sh.num_subsets() );
    6630              : 
    6631            0 :                 m_sh.assign_subset( shiftDirectionEdg->vertex(0), strangeSubs );
    6632            0 :                 m_sh.assign_subset( shiftDirectionEdg->vertex(1), strangeSubs );
    6633            0 :                 m_sh.assign_subset( oldVrt, strangeSubs );
    6634              : 
    6635              : 
    6636              :                 UG_LOG("computing cross point end false " << std::endl);
    6637              : 
    6638            0 :                 return false;
    6639              :         }
    6640              : 
    6641              :         UG_LOG("computing cross point end true " << std::endl);
    6642              : 
    6643              : 
    6644              :         return true;
    6645              : 
    6646              : }
    6647              : //////////////////////////////////////////////////////////////////////////
    6648              : 
    6649              : 
    6650              : #if 0
    6651              : template<>
    6652              : bool ArteExpandFracs3D::expandWithinTheSegment<1,false>( Vertex * const & oldVrt, SegmentVolElmInfo const & segmVolElmInfo )
    6653              : {
    6654              : 
    6655              :         // get all fracture faces, check if they belong to the same subdomain, must be the case here!
    6656              : 
    6657              :         VecAttachedFractFaceEdgeSudo vecAttFractFaces;
    6658              : 
    6659              :         for( AttachedVolumeElemInfo const & avei : segmVolElmInfo )
    6660              :         {
    6661              :                 VecAttachedFractFaceEdgeSudo const & vecAttFractVol = avei.getVecFractManifElem();
    6662              : 
    6663              :                 for( AttachedFractFaceEdgeSudo const & affe : vecAttFractVol )
    6664              :                 {
    6665              :                         vecAttFractFaces.push_back(affe);
    6666              :                 }
    6667              :         }
    6668              : 
    6669              :         IndexType numbContrFracFaces = vecAttFractFaces.size();
    6670              : 
    6671              :         if( numbContrFracFaces < 1 )
    6672              :         {
    6673              :                 UG_LOG("Kein Affe da " << std::endl);
    6674              :                 UG_THROW("Kein Affe da " << std::endl);
    6675              :                 return false;
    6676              :         }
    6677              : 
    6678              :         IndexType sudoBase = vecAttFractFaces[0].getSudo();
    6679              : 
    6680              :         // check if all sudos equal
    6681              :         for( AttachedFractFaceEdgeSudo const & affe : vecAttFractFaces )
    6682              :         {
    6683              :                 IndexType sudoTest = affe.getSudo();
    6684              : 
    6685              :                 if( sudoTest != sudoBase )
    6686              :                 {
    6687              :                         UG_LOG("unterschiedliche Sudos an einer einzelnen Fracture?" << std::endl);
    6688              :                         UG_THROW("unterschiedliche Sudos an einer einzelnen Fracture?" << std::endl);
    6689              :                         return false;
    6690              :                 }
    6691              :         }
    6692              : 
    6693              :         // now we are sure we have the same sudo, now we average the normals
    6694              : 
    6695              :         NormalVectorFacIntoVol normalsFacInVolSummed(0,0,0);
    6696              : 
    6697              :         for( AttachedFractFaceEdgeSudo const & affe : vecAttFractFaces )
    6698              :         {
    6699              :                 NormalVectorFacIntoVol tmpVec = normalsFacInVolSummed;
    6700              :                 UG_LOG("Normal Vec " << tmpVec << std::endl);
    6701              :                 VecAdd(normalsFacInVolSummed, tmpVec, affe.getNormalVec() );
    6702              :         }
    6703              : 
    6704              :         NormalVectorFacIntoVol normalsAveraged;
    6705              : 
    6706              :         VecScale( normalsAveraged, normalsFacInVolSummed, 1. / ( static_cast<number>(numbContrFracFaces) ) );
    6707              : 
    6708              :         number width = m_fracInfosBySubset[sudoBase].width;
    6709              : 
    6710              :         number scal = width / 2.;
    6711              : 
    6712              :         NormalVectorFacIntoVol scaledNormal;
    6713              : 
    6714              :         VecScale( scaledNormal, normalsAveraged, - scal );
    6715              : 
    6716              :         vector3 posOldVrt = m_aaPos[oldVrt];
    6717              : 
    6718              :         vector3 posNewVrt;
    6719              : 
    6720              :         VecAdd( posNewVrt, posOldVrt, scaledNormal );
    6721              : 
    6722              :         Vertex * newShiftVrtx = *m_grid.create<RegularVertex>();
    6723              : 
    6724              :         if( newShiftVrtx == nullptr )
    6725              :         {
    6726              :                 UG_LOG("Nullen erzeugt" << std::endl);
    6727              :                 UG_THROW("Nullen erzeugt" << std::endl);
    6728              :                 return false;
    6729              :         }
    6730              : 
    6731              :         m_aaPos[newShiftVrtx] = posNewVrt;
    6732              : 
    6733              :         UG_LOG("Created new vertex at " << m_aaPos[newShiftVrtx] << std::endl );
    6734              : 
    6735              :         m_sh.assign_subset(newShiftVrtx, sudoBase);
    6736              : 
    6737              :         for( AttachedVolumeElemInfo const & avei : segmVolElmInfo )
    6738              :         {
    6739              :                 Volume * vol = avei.getFulldimElem();
    6740              : 
    6741              :                 std::vector<Vertex*> & newVrts4Fac = m_aaVrtVecVol[ vol ];
    6742              : 
    6743              :                 for(size_t indVrt = 0; indVrt < (vol)->num_vertices();  indVrt++ )
    6744              :                 {
    6745              :                         Vertex* volVrt = (vol)->vertex(indVrt);
    6746              : 
    6747              :                         if(  volVrt == oldVrt )
    6748              :                         {
    6749              :                                 newVrts4Fac[ indVrt ] = newShiftVrtx;
    6750              :                         }
    6751              :                 }
    6752              :         }
    6753              : 
    6754              :         return true;
    6755              : }
    6756              : #endif
    6757              : 
    6758              : 
    6759              : ////////////////////////////////////////////////////////////////////
    6760              : 
    6761              : //template<ArteExpandFracs3D::SegmentVrtxFracStatus::oneFracSuDoAtt>
    6762              : //bool ArteExpandFracs3D::computeShiftVector( ArteExpandFracs3D::VecSegmentLimitSidesPairSudoNorml const & vecSegmLimSidPrSudoNrml )
    6763              : //{
    6764              : //      return {};
    6765              : //}
    6766              : 
    6767              : 
    6768              : ////////////////////////////////////////////////////////////////////
    6769              : 
    6770              : // TODO FIXME muss verschwinden!
    6771              : //template<>
    6772              : //bool ArteExpandFracs3D::computeShiftVector( VecSegmentLimitSidesPairSudoNorml const & vecSegmLimSidPrSudoNrml )
    6773              : ////bool ArteExpandFracs3D::expandWithinTheSegment<ArteExpandFracs3D::SegmentVrtxFracStatus::threeFracSuDoAtt>( SegmentLimitingSides const & segmLimSides )
    6774              : //{
    6775              : //      // wenn es nur zwei Segmentnormalen und sudos sind, dann wird die dritte auf Normale senkrecht zu
    6776              : //      // den beiden anderen gesetzt, und um Null verschoben, ihr
    6777              : //
    6778              : ////    if( segmLimSides.isBoundary() )
    6779              : ////    {
    6780              : ////            UG_LOG("three fracture at boundary need implementation " << std::endl);
    6781              : ////            UG_THROW("three fracture at boundary need implementation " << std::endl);
    6782              : ////            return false;
    6783              : ////    }
    6784              : //
    6785              : ////    VecSegmentLimitSidesPairSudoNorml vecSegmLimSidPrSudoNrml;
    6786              : //
    6787              : //      Vertex * oldVrt = segmLimSides.spuckVertex();
    6788              : //
    6789              : //      if( ! segmLimSides.spuckFractSudoNormls( vecSegmLimSidPrSudoNrml ) )
    6790              : //      {
    6791              : //              UG_LOG("Spucken schief gegangen three " << std::endl);
    6792              : //              UG_THROW("Spucken schief gegangen three " << std::endl);
    6793              : //              return false;
    6794              : //      }
    6795              : //
    6796              : //      if( vecSegmLimSidPrSudoNrml.size() != 3 )
    6797              : //      {
    6798              : //              UG_LOG("three fractures, but not three normals and sudo?"  <<  std::endl);
    6799              : //              UG_THROW("three fracture, but not three normal and sudo?" << std::endl);
    6800              : //              return false;
    6801              : //      }
    6802              : //
    6803              : //      // select one of the sudos of the sourrounding sudos of the segment, to which we want to assign the new vertex
    6804              : //      IndexType sudoExample = (vecSegmLimSidPrSudoNrml[0]).first;
    6805              : //
    6806              : ////    std::vector<IndexType> vecSudosSides;
    6807              : ////    std::vector<vector3> vecNormalsAveraged;
    6808              : ////    std::vector<vector3> vecShiftVec4Plane;
    6809              : //
    6810              : //      vector3 posOldVrt = m_aaPos[oldVrt];
    6811              : //
    6812              : //      VecPlaneDescriptor vecShiftedPlaneDescript;
    6813              : //
    6814              : ////    IndexType side = 0;
    6815              : //
    6816              : //      for( SegmentLimitSidesPairSudoNorml const & segLimSidPrSN : vecSegmLimSidPrSudoNrml )
    6817              : //      {
    6818              : //              IndexType const & sudoSide = segLimSidPrSN.first;
    6819              : //              vector3 const & normlAvrg = segLimSidPrSN.second;
    6820              : //
    6821              : //              // normal computed standard mässig directs of of the volume, we need that one into the volume
    6822              : //              vector3 normalOutsideVol;
    6823              : //
    6824              : //              // hier testen, ob die Subdomain von der Liste der fracture subdomains ist,
    6825              : //              // damit für den Fall von sich zwei schneidenden Ebenen für die dritte,
    6826              : //              // die als senkrecht zu den beiden anderen gesetzt werden soll, mit Verschiebung null,
    6827              : //              // analog Boundary sides, die künstliche Weite null erhalten kann hier
    6828              : //              number width = 0;
    6829              : //
    6830              : //              // ensure that the width is nonzero only for real fractures, not for pseudo vectors or such stuff
    6831              : //              if( ( side == 1 && ! artificialNormalTwo ) ||  ( side == 2 && ! artificialNormalThree ) )
    6832              : //                      width = m_fracInfosBySubset[sudoSide].width;
    6833              : //
    6834              : //              side++;
    6835              : //
    6836              : //              number shiftScal = width / 2.;
    6837              : //
    6838              : //              vector3 shiftVec4Plane;
    6839              : //
    6840              : //              // as normal outside vol, but we need to go inside the volumes / segment side
    6841              : //              VecScale( shiftVec4Plane, normalOutsideVol, - shiftScal );
    6842              : //
    6843              : ////            vecShiftVec4Plane.push_back( shiftVec4Plane );
    6844              : ////            vecSudosSides.push_back( sudoSide );
    6845              : ////            vecNormalsAveraged.push_back( normalIntoVol );
    6846              : //
    6847              : //              PlaneDescriptor planeDescr( normalOutsideVol, posOldVrt );
    6848              : //
    6849              : //              PlaneDescriptor shiftedPlaneDescr;
    6850              : //
    6851              : //              planeDescr.spuckPlaneShiftedAlong( shiftVec4Plane, shiftedPlaneDescr );
    6852              : //
    6853              : //              vecShiftedPlaneDescript.push_back( shiftedPlaneDescr );
    6854              : //      }
    6855              : //
    6856              : //      // KÄSE alles!!! wenn es eine boundary ist oder eine Kreuzung von zwei Ebenen innendrin,
    6857              : //      // dann muss hier DANACH noch was dazu kommen, das heisst, alles, was hier gemacht wird,
    6858              : //      // soll für den Fall sein, dass es keine einzelne Fracture innen drin ist,
    6859              : //      // und alle bool template Parameter sind MÜLL!!!!
    6860              : //      // das für zwei Fractures muss hier auch dazu
    6861              : //      // vielleicht am einfachsten, wenn man den template parameter auf true oder false stellt
    6862              : //      // für eine fracture innen oder allen anderen Rest......
    6863              : //
    6864              : //      // TODO FIXME compute crossing point of the three new planes!!!! need functions from lib_disc, cf FiniteStrainMechanics, solve LGS exact
    6865              : //
    6866              : //      vector3 shiftedCrossingPoint;
    6867              : //
    6868              : //      computeCrossingPointOf3Planes( vecShiftedPlaneDescript, shiftedCrossingPoint );
    6869              : //
    6870              : //      return true;
    6871              : //}
    6872              : 
    6873              : ////////////////////////////////////////////////////////////////////
    6874              : 
    6875            0 : bool ArteExpandFracs3D::computeCrossingPointOf3Planes(  VecPlaneDescriptor const & vecPlaneDescr, vector3 & crossingPoint )
    6876              : {
    6877              :         // n_i * vecX_i = a_i * n_i , i=1,2,3, ohne Summenkonvention, und n_i, vecX_i, a_i jeweils Vektoren Grösse 3
    6878              :         // es entsteht also ein LGS für drei Unbekannte und drei Gleichungen
    6879              : 
    6880              : //       vector<vector<double>> coefficients = {{2, 1}, {1, -3}};
    6881              : //       vector<double> constants = {5, -1};
    6882              : //       vector<double> solutions = cramer_rule(coefficients, constants);
    6883              : //       cout << "Solution for x: " << solutions[0] << endl;
    6884              : //       cout << "Solution for y: " << solutions[1] << endl;
    6885              : 
    6886              :         PlaneDescriptor const & planeDescrZero = vecPlaneDescr[0];
    6887              :         PlaneDescriptor const & planeDescrOne = vecPlaneDescr[1];
    6888              :         PlaneDescriptor const & planeDescrTwo = vecPlaneDescr[2];
    6889              : 
    6890              :         vector3 const & normalZero = planeDescrZero.spuckNormalVector();
    6891              :         vector3 const & normalOne = planeDescrOne.spuckNormalVector();
    6892              :         vector3 const & normalTwo = planeDescrTwo.spuckNormalVector();
    6893              : 
    6894              :         number const & rhsZero = planeDescrZero.spuckRHS();
    6895              :         number const & rhsOne = planeDescrOne.spuckRHS();
    6896              :         number const & rhsTwo = planeDescrTwo.spuckRHS();
    6897              : 
    6898              : 
    6899              : 
    6900              :         std::vector<std::vector<double>> coefficients = { {normalZero[0], normalZero[1], normalZero[2]},
    6901              :                                                                                                           {normalOne[0], normalOne[1], normalOne[2]},
    6902              :                                                                                                           {normalTwo[0], normalTwo[1], normalTwo[2]},
    6903            0 :                                                                                                         };
    6904              : 
    6905            0 :         std::vector<double> constants = { rhsZero, rhsOne, rhsTwo };
    6906              : 
    6907            0 :         std::vector<double> solutions = ug::simpleMatrOps::cramerRule(coefficients, constants);
    6908              : 
    6909            0 :         crossingPoint = vector3( solutions[0], solutions[1], solutions[2] );
    6910              : 
    6911            0 :         return true;
    6912            0 : }
    6913              : 
    6914              : ////////////////////////////////////////////////////////////////////
    6915              : 
    6916              : 
    6917              : 
    6918              : #if 0
    6919              : //template <>
    6920              : //bool ArteExpandFracs3D::establishNewVertices< Tetrahedron,
    6921              : //                                                                                        ArteExpandFracs3D::VrtxFracProptsStatus::oneFracSuDoAtt
    6922              : //                                                                                      >( Vertex * const & oldVrt )
    6923              : //template< bool APPLY_GENERAL_SEGMENT_ORDERING,
    6924              : //                ArteExpandFracs3D::VrtxFracProptsStatus vfp,
    6925              : //                typename std::enable_if< std::integral_constant<bool,APPLY_GENERAL_SEGMENT_ORDERING>>
    6926              : //              >
    6927              : template <>
    6928              : bool ArteExpandFracs3D::establishNewVertices< true,
    6929              :                                                                                           ArteExpandFracs3D::VrtxFracProptsStatus::oneFracSuDoAtt
    6930              :                                                                                         >( Vertex * const & oldVrt )
    6931              : {
    6932              :         UG_LOG("under construction Tetrahedra limited" << std::endl);
    6933              : 
    6934              :         VecVertFracTrip const & vecVertFracTrip = m_aaVrtInfoFraTri[oldVrt];
    6935              : 
    6936              :         VecAttachedVolumeElemInfo const & vecAttVolElemInfo = m_aaVolElmInfo[oldVrt];
    6937              : 
    6938              :         VecAttachedVolumeElemInfo vecAttVolElemInfoCop = vecAttVolElemInfo; // echte KOPIE
    6939              : 
    6940              :         VecAttachedVolumeElemInfo reconstructedVecAttVolElmInf;
    6941              : 
    6942              :         VecSegmentVolElmInfo vecSegVolElmInfo;
    6943              : 
    6944              :                 /*
    6945              :                  * While Schleifen aufbauen für den
    6946              :                  * Search the adjacent surface interatively - Algorithmus
    6947              :                  * (Stasi Algorithmus)
    6948              :                  *
    6949              :                  */
    6950              : 
    6951              :         IndexType d_segmenteErledigt = 0;
    6952              : 
    6953              :         while( vecAttVolElemInfoCop.size() != 0 )
    6954              :         {
    6955              :                 SegmentVolElmInfo segmentAVEI;
    6956              : 
    6957              :                 AttachedVolumeElemInfo & startVolInfoThisSegment = vecAttVolElemInfoCop[0];
    6958              : 
    6959              :                 startVolInfoThisSegment.markIt();
    6960              : 
    6961              :                 Volume * volSta = startVolInfoThisSegment.getFulldimElem();
    6962              : 
    6963              :                 vector3 center;
    6964              : 
    6965              :                 if( volSta != nullptr )
    6966              :                         center = CalculateCenter(volSta,m_aaPos);
    6967              : 
    6968              : //              UG_LOG("volume center " << center << std::endl );
    6969              : 
    6970              :                 int d_loopsDone = 0;
    6971              : 
    6972              :                 while( vecAttVolElemInfoCop.size() != 0 )
    6973              :                 {
    6974              :                         // count number of marked elements
    6975              :                         IndexType numMarkedElems = 0;
    6976              :                         IndexType markPoint = 0;
    6977              : 
    6978              : //                      IndexType lastMarkPt = 0;
    6979              :                         IndexType startIndexInner = 0;
    6980              : 
    6981              :                         for( AttachedVolumeElemInfo const & volElInfCop : vecAttVolElemInfoCop )
    6982              :                         {
    6983              :                                 if( volElInfCop.isMarked() )
    6984              :                                 {
    6985              :                                         Volume * vol = volElInfCop.getFulldimElem();
    6986              : //                                      m_sh.assign_subset(vol, m_sh.num_subsets());
    6987              : 
    6988              :                                         vector3 center = CalculateCenter(vol,m_aaPos);
    6989              : 
    6990              : //                                      UG_LOG("DAS ZENTRUM " << numMarkedElems << " -> " << center << std::endl);
    6991              : 
    6992              :                                         startIndexInner = markPoint;
    6993              :                                         numMarkedElems++;
    6994              : 
    6995              :                                 }
    6996              : 
    6997              :                                 markPoint++;
    6998              :                         }
    6999              : 
    7000              :                         UG_LOG("LOOPS DONE " << numMarkedElems << std::endl);
    7001              : 
    7002              :                         if( numMarkedElems == 0 )
    7003              :                                 break;
    7004              : 
    7005              : //                      int startIndexInner = -1;
    7006              : //
    7007              : //                      for( int i = 0; i < vecAttVolElemInfoCop.size(); i++ )
    7008              : //                      {
    7009              : //                              AttachedVolumeElemInfo vi = vecAttVolElemInfoCop[i];
    7010              : //
    7011              : //                              Volume * vo = vi.getFulldimElem();
    7012              : //
    7013              : //                              vector3 center = CalculateCenter(vo,m_aaPos);
    7014              : //
    7015              : //                              UG_LOG("DAS ZENTRUM ZAHL VOR " << i << " -> " <<  center << std::endl);
    7016              : //
    7017              : //                              if( vi.isMarked() )
    7018              : //                                      startIndexInner = i;
    7019              : //                      }
    7020              : //
    7021              : //                      if( startIndexInner < 0 )
    7022              : //                      {
    7023              : //                              UG_THROW("kein Anfang gefunden " << std::endl);
    7024              : //                      }
    7025              : //
    7026              : //#if 0
    7027              : //                      IndexType startIndexInner = markPoint - 1;
    7028              : //#endif
    7029              :                         AttachedVolumeElemInfo startVolInfoMarkLoop = vecAttVolElemInfoCop[startIndexInner];
    7030              : 
    7031              :                         Volume * stattVoll = startVolInfoMarkLoop.getFulldimElem();
    7032              : 
    7033              :                         vector3 centerX = CalculateCenter(stattVoll,m_aaPos);
    7034              : 
    7035              :                         UG_LOG("DAS ZENTRUM DANACH " << startIndexInner << " -> " <<  centerX << std::endl);
    7036              : 
    7037              : //                      m_sh.assign_subset(stattVoll, m_sh.num_subsets());
    7038              : #if 0
    7039              :                         for( int i = 0; i < vecAttVolElemInfoCop.size(); i++ )
    7040              :                         {
    7041              :                                 AttachedVolumeElemInfo vi = vecAttVolElemInfoCop[i];
    7042              : 
    7043              :                                 Volume * vo = vi.getFulldimElem();
    7044              : 
    7045              :                                 vector3 center = CalculateCenter(vo,m_aaPos);
    7046              : 
    7047              :                                 UG_LOG("DAS ZENTRUM ZAHL " << i << " -> " <<  center << std::endl);
    7048              : 
    7049              :                         }
    7050              : #endif
    7051              :                         for( AttachedVolumeElemInfo const & possibleOrigVolInfo : vecAttVolElemInfo )
    7052              :                         {
    7053              :                                 if( possibleOrigVolInfo.hasSameFulldimElem( startVolInfoMarkLoop ) )
    7054              :                                 {
    7055              :                                         segmentAVEI.push_back(possibleOrigVolInfo);
    7056              :                                         reconstructedVecAttVolElmInf.push_back(possibleOrigVolInfo);
    7057              :                                         break;
    7058              :                                 }
    7059              :                         }
    7060              : 
    7061              :                         vecAttVolElemInfoCop.erase( vecAttVolElemInfoCop.begin() + startIndexInner );
    7062              : 
    7063              : //                      if( d_loopsDone == 1 )
    7064              : //                              return false;
    7065              : 
    7066              :                         for( VecAttachedVolumeElemInfo::iterator aveiIt = vecAttVolElemInfoCop.begin();
    7067              :                                                                                                          aveiIt < vecAttVolElemInfoCop.end();
    7068              :                                                                                                          aveiIt++
    7069              :                         )
    7070              :                         {
    7071              :                                 AttachedVolumeElemInfo & possibleNeighbour = *aveiIt;
    7072              : 
    7073              :                                 if( possibleNeighbour.hasSameFulldimElem( startVolInfoMarkLoop ) )
    7074              :                                 {
    7075              :                                         continue;
    7076              :                                 }
    7077              :                                 else
    7078              :                                 {
    7079              :                                         bool neighbourFound = possibleNeighbour.testFullDimElmNeighbour( startVolInfoMarkLoop );
    7080              : 
    7081              :                                         if( neighbourFound )
    7082              :                                         {
    7083              :                                                 Volume * vol = possibleNeighbour.getFulldimElem();
    7084              : 
    7085              : //                                              m_sh.assign_subset(vol, m_sh.num_subsets());
    7086              : 
    7087              :                                         }
    7088              :                                 }
    7089              :                         }
    7090              : 
    7091              : 
    7092              :                         d_loopsDone++;
    7093              : 
    7094              : 
    7095              :                 }
    7096              : 
    7097              :                 vecSegVolElmInfo.push_back(segmentAVEI);
    7098              : 
    7099              : //              d_segmenteErledigt++;
    7100              : //
    7101              : //              if( d_segmenteErledigt == 1 )
    7102              : //              return false;
    7103              :         }
    7104              : 
    7105              :         if( reconstructedVecAttVolElmInf.size() != vecAttVolElemInfo.size() )
    7106              :         {
    7107              :                 UG_LOG("Rekonstruktion schief gegangen " << std::endl);
    7108              :                 UG_THROW("Rekonstruktion schief gegangen " << std::endl);
    7109              :                 return false;
    7110              :         }
    7111              : 
    7112              :         for( SegmentVolElmInfo const & svei : vecSegVolElmInfo )
    7113              :         {
    7114              :                 // TODO FIXME das hier wieder entfernen, die Subdomain Zuweisung, nur für debug Zwecke
    7115              :                 IndexType sudoMax = m_sh.num_subsets();
    7116              : 
    7117              :                 for( AttachedVolumeElemInfo const & vei : svei )
    7118              :                 {
    7119              :                         Volume * vol = vei.getFulldimElem();
    7120              : 
    7121              :                         m_sh.assign_subset( vol, sudoMax );
    7122              :                 }
    7123              :         }
    7124              : 
    7125              :         return true;
    7126              : }
    7127              : 
    7128              : 
    7129              : ////////////////////////////////////////////////////////////////////
    7130              : 
    7131              : 
    7132              : 
    7133              : //template <>
    7134              : //bool ArteExpandFracs3D::establishNewVertices< Hexahedron,
    7135              : //                                                                                        ArteExpandFracs3D::VrtxFracProptsStatus::oneFracSuDoAtt
    7136              : //                                                                                      >( Vertex * const & oldVrt )
    7137              : //template< bool APPLY_GENERAL_SEGMENT_ORDERING,
    7138              : //                ArteExpandFracs3D::VrtxFracProptsStatus vfp,
    7139              : //                typename std::enable_if< std::integral_constant<bool,!APPLY_GENERAL_SEGMENT_ORDERING>>
    7140              : //              >
    7141              : template <>
    7142              : bool ArteExpandFracs3D::establishNewVertices< false,
    7143              :                                                                                           ArteExpandFracs3D::VrtxFracProptsStatus::oneFracSuDoAtt
    7144              :                                                                                         >( Vertex * const & oldVrt )
    7145              : {
    7146              :         VecVertFracTrip & vecVertFracTrip = m_aaVrtInfoFraTri[oldVrt];
    7147              : 
    7148              : //      std::vector<Edge*> & allAssoEdges = m_aaVrtInfoAssoEdges[oldVrt];
    7149              : //      std::vector<Face*> & allAssoFaces = m_aaVrtInfoAssoFaces[oldVrt];
    7150              : //      std::vector<Volume*> & allAssoVolumes = m_aaVrtInfoAssoVols[oldVrt];
    7151              : 
    7152              :         // TODO FIXME works if at all only for very simple geometries
    7153              :         // and works only in particular if all asso volumes are part of the triple, i.e. have all a common face with the fracture
    7154              :         // this is not selbstverständlich at all!!!!
    7155              : 
    7156              :         VecVertFracTrip  vecVertFracTripCopy = m_aaVrtInfoFraTri[oldVrt]; // copy, not reference!
    7157              : 
    7158              : 
    7159              :         VecVertFracTrip firstSegment;
    7160              :         VecVertFracTrip secondSegment;
    7161              : 
    7162              :         IndexType beginIndex = 0;
    7163              : 
    7164              :         VertFracTrip startTrip = vecVertFracTripCopy[beginIndex];
    7165              : 
    7166              :         firstSegment.push_back( startTrip );
    7167              : 
    7168              :         vector3 normalOne = startTrip.getNormal();
    7169              :         vector3 normalTwo;
    7170              :         // vermute einfach umgekehrte Normale, ein Trick, der im einfachsten Fall geht......
    7171              :         VecScale(normalTwo,normalOne,-1);
    7172              : 
    7173              :         vecVertFracTripCopy.erase( vecVertFracTripCopy.begin() + beginIndex );
    7174              : 
    7175              : //      for( VecVertFracTrip::iterator itVFT  = vecVertFracTripCopy.begin();
    7176              : //                                                                         itVFT != vecVertFracTripCopy.end();
    7177              : //                                                                         itVFT++
    7178              : //              )
    7179              : //              {
    7180              : //                      VertFracTrip actualVFT = *itVFT;
    7181              : //
    7182              : //                      vector3 volCenter = CalculateCenter(actualVFT.getFullElm(),m_aaPos);
    7183              : //                      UG_LOG("Vol center" << volCenter << std::endl);
    7184              : //                      vecVertFracTripCopy.erase(itVFT);
    7185              : //              }
    7186              : //
    7187              : //      return true;
    7188              : 
    7189              : //      while( vecVertFracTripCopy.size() != 0 )
    7190              : //      {
    7191              : //              for( VecVertFracTrip::iterator itVFT  = vecVertFracTripCopy.begin();
    7192              : //                                                                         itVFT != vecVertFracTripCopy.end();
    7193              : //                                                                         itVFT++
    7194              : //              )
    7195              :         for( auto const & actualVFT : vecVertFracTripCopy )
    7196              :         {
    7197              : //                      VertFracTrip actualVFT = *itVFT;
    7198              : 
    7199              :                 vector3 normalActual = actualVFT.getNormal();
    7200              : 
    7201              :                 vector3 volCenter = CalculateCenter(actualVFT.getFullElm(),m_aaPos);
    7202              :                 UG_LOG("Vol center" << volCenter << std::endl);
    7203              : 
    7204              :                 // test direction
    7205              : 
    7206              :                 number cosinus2One = VecDot(normalOne,normalActual);
    7207              :                 number cosinus2Two = VecDot(normalTwo,normalActual);
    7208              : 
    7209              :                 UG_LOG("normal eins " << normalOne << std::endl);
    7210              :                 UG_LOG("normal zwei " << normalTwo << std::endl);
    7211              :                 UG_LOG("normal actu " << normalActual << std::endl);
    7212              : 
    7213              :                 UG_LOG("cosi one " << cosinus2One << std::endl );
    7214              :                 UG_LOG("cosi two " << cosinus2Two << std::endl );
    7215              : 
    7216              : 
    7217              :                 // if cosinus > 0, assume same side
    7218              : 
    7219              :                 if( ( cosinus2One >= 0 && cosinus2Two >= 0 ) || ( cosinus2One <= 0 && cosinus2Two <= 0 ) )
    7220              :                         UG_THROW("kann nicht auf zwei Seiten hinken" << std::endl);
    7221              : 
    7222              :                 if( cosinus2One >= 0 )
    7223              :                 {
    7224              :                         firstSegment.push_back( actualVFT );
    7225              :                 }
    7226              :                 else if( cosinus2Two >= 0 )
    7227              :                 {
    7228              :                         secondSegment.push_back( actualVFT );
    7229              :                 }
    7230              :                 else
    7231              :                 {
    7232              :                         UG_THROW("muss wo dazu gehoeren wohl" << std::endl);
    7233              :                 }
    7234              :         }
    7235              : //                      vecVertFracTripCopy.erase(itVFT);
    7236              : //              }
    7237              : //      }
    7238              : 
    7239              :         // computer averaged normal
    7240              : 
    7241              :         vector3 normalsOneSummed(0,0,0);
    7242              :         vector3 normalsTwoSummed(0,0,0);
    7243              : 
    7244              : 
    7245              :         for( auto const & seg: firstSegment )
    7246              :         {
    7247              :                 vector3 tmpVec = normalsOneSummed;
    7248              :                 VecAdd(normalsOneSummed,tmpVec,seg.getNormal());
    7249              :         }
    7250              : 
    7251              :         for( auto const & seg: secondSegment )
    7252              :         {
    7253              :                 vector3 tmpVec = normalsTwoSummed;
    7254              :                 VecAdd(normalsTwoSummed,tmpVec,seg.getNormal());
    7255              :         }
    7256              : 
    7257              :         vector3 normalsOneAveraged;
    7258              :         vector3 normalsTwoAveraged;
    7259              : 
    7260              :         if( firstSegment.size() != 0 )
    7261              :         {
    7262              :                 VecScale(normalsOneAveraged, normalsOneSummed, 1./firstSegment.size());
    7263              :         }
    7264              : 
    7265              :         if( secondSegment.size() != 0 )
    7266              :         {
    7267              :                 VecScale(normalsTwoAveraged, normalsTwoSummed, 1./secondSegment.size());
    7268              :         }
    7269              : 
    7270              :         // get to know width of fracture
    7271              : 
    7272              :         IndexType suse = startTrip.getSudoElm();
    7273              : 
    7274              :         number width = m_fracInfosBySubset[suse].width;
    7275              : 
    7276              :         number scal = width / 2.;
    7277              : 
    7278              :         vector3 scaledNormalOne, scaledNormalTwo;
    7279              :         VecScale( scaledNormalOne, normalOne, - scal );
    7280              :         VecScale( scaledNormalTwo, normalTwo, - scal );
    7281              :         // Minuszeichen wichtig, sonst wird in die falsche Richtung gedrückt, und die Volumen gehen über die fracture
    7282              :         // raus und werden grösser, anstatt kleiner zu werden.....
    7283              : 
    7284              :         vector3 posOldVrt = m_aaPos[oldVrt];
    7285              : 
    7286              :         vector3 posNewVrtOne, posNewVrtTwo;
    7287              : 
    7288              :         VecAdd( posNewVrtOne, posOldVrt, scaledNormalOne);
    7289              :         VecAdd( posNewVrtTwo, posOldVrt, scaledNormalTwo);
    7290              : 
    7291              :         Vertex * newShiftVrtxOne = *m_grid.create<RegularVertex>();
    7292              :         Vertex * newShiftVrtxTwo = *m_grid.create<RegularVertex>();
    7293              : 
    7294              :         m_aaPos[newShiftVrtxOne] = posNewVrtOne;
    7295              :         m_aaPos[newShiftVrtxTwo] = posNewVrtTwo;
    7296              : 
    7297              :         UG_LOG("Created new vertex 1 at " <<m_aaPos[newShiftVrtxOne] << std::endl );
    7298              :         UG_LOG("Created new vertex 2 at " <<m_aaPos[newShiftVrtxTwo] << std::endl );
    7299              : 
    7300              :         m_sh.assign_subset(newShiftVrtxOne, suse);
    7301              :         m_sh.assign_subset(newShiftVrtxTwo, suse);
    7302              : 
    7303              : //      m_sh.assign_subset(newShiftVrtxOne, 3);
    7304              : //      m_sh.assign_subset(newShiftVrtxTwo, 3);
    7305              : 
    7306              :         for( auto const & fs : firstSegment )
    7307              :         {
    7308              :                 Volume * vol = fs.getFullElm();
    7309              : 
    7310              :                 std::vector<Vertex*>& newVrts4Fac = m_aaVrtVecVol[ vol ];
    7311              : 
    7312              :                 for(size_t indVrt = 0; indVrt < (vol)->num_vertices();  indVrt++ )
    7313              :                 {
    7314              :                         Vertex* volVrt = (vol)->vertex(indVrt);
    7315              : 
    7316              :                         if(  volVrt == oldVrt )
    7317              :                         {
    7318              :                                 newVrts4Fac[ indVrt ] = newShiftVrtxOne;
    7319              :                         }
    7320              :                 }
    7321              :         }
    7322              : 
    7323              :         for( auto const & ses : secondSegment )
    7324              :         {
    7325              :                 Volume * vol = ses.getFullElm();
    7326              : 
    7327              :                 std::vector<Vertex*>& newVrts4Fac = m_aaVrtVecVol[ vol ];
    7328              : 
    7329              :                 for(size_t indVrt = 0; indVrt < (vol)->num_vertices();  indVrt++ )
    7330              :                 {
    7331              :                         Vertex* volVrt = (vol)->vertex(indVrt);
    7332              : 
    7333              :                         if(  volVrt == oldVrt )
    7334              :                         {
    7335              :                                 newVrts4Fac[ indVrt ] = newShiftVrtxTwo;
    7336              :                         }
    7337              :                 }
    7338              :         }
    7339              : 
    7340              : 
    7341              :         return true;
    7342              : }
    7343              : 
    7344              : #endif
    7345              : 
    7346              : ////////////////////////////////////////////////////////////////////
    7347              : 
    7348              : 
    7349            0 : bool ArteExpandFracs3D::createConditionForNewVrtcs()
    7350              : {
    7351              : 
    7352              :         //      iterate over all surrounding volumes to enable volume changes, this loop taken from SR but shortened
    7353            0 :         for(VolumeIterator iterSurrVol = m_sel.volumes_begin(); iterSurrVol != m_sel.volumes_end(); iterSurrVol++ )
    7354              :         {
    7355              :                 Volume * sv = *iterSurrVol;
    7356              : 
    7357              :                 std::vector<Vertex*>& newVrts = m_aaVrtVecVol[sv];
    7358            0 :                 newVrts.resize(sv->num_vertices());
    7359              : 
    7360            0 :                 for(size_t iVrt = 0; iVrt < sv->num_vertices(); iVrt++ )
    7361              :                 {
    7362            0 :                         newVrts[iVrt] = nullptr;
    7363              :                 }
    7364              :                         // erstmal so tun, als ob keine neuen Vertizes erzeugt werden an den alten Vertizes
    7365              :         }
    7366              : 
    7367              : 
    7368            0 :         return true;
    7369              : }
    7370              : 
    7371              : /////////////////////////////////////////////////////////////
    7372              : 
    7373            0 : bool ArteExpandFracs3D::createNewElements()
    7374              : {
    7375              :         // originally practically copied from Sebastian, as this concept was fine for 2D, but adapted in 3D
    7376              : 
    7377              :         //      create new elements
    7378              : 
    7379              :         UG_LOG("want to create new elems" << std::endl );
    7380              : 
    7381              :         //      holds local side vertex indices
    7382              :         std::vector<size_t>       locVrtInds;
    7383              : 
    7384              :         //      first we create new edges from selected ones which are connected to
    7385              :         //      inner vertices. This allows to preserve old subsets.
    7386              :         //      Since we have to make sure that we use the right vertices,
    7387              :         //      we have to iterate over the selected volumes and perform all actions on the edges
    7388              :         //      of those volumes.
    7389            0 :         for(VolumeIterator iter_sv = m_sel.volumes_begin(); iter_sv != m_sel.volumes_end(); ++iter_sv)
    7390              :         {
    7391              :                 Volume* sv = *iter_sv;
    7392              : 
    7393            0 :                 UG_LOG("entering volume to create new elems " << CalculateCenter(sv, m_aaPos) << std::endl);
    7394              : 
    7395              :                 //      check for each edge whether it has to be copied.
    7396            0 :                 for(size_t i_edge = 0; i_edge < sv->num_edges(); ++i_edge)
    7397              :                 {
    7398            0 :                         Edge* e = m_grid.get_edge(sv, i_edge);
    7399              : 
    7400            0 :                         if(m_sel.is_selected(e))
    7401              :                         {
    7402              :                                 //      check the associated vertices through the volumes aaVrtVecVol attachment.
    7403              :                                 //      If at least one has an associated new vertex and if no edge between the
    7404              :                                 //      new vertices already exists, we'll create the new edge.
    7405              :                                 size_t ind0, ind1;
    7406            0 :                                 sv->get_vertex_indices_of_edge(ind0, ind1, i_edge);
    7407            0 :                                 Vertex* nv0 = (m_aaVrtVecVol[sv])[ind0];
    7408            0 :                                 Vertex* nv1 = (m_aaVrtVecVol[sv])[ind1];
    7409              : 
    7410            0 :                                 if(nv0 || nv1)
    7411              :                                 {
    7412              :                                         //      if one vertex has no associated new one, then we use the vertex itself
    7413            0 :                                         if(!nv0)
    7414            0 :                                                 nv0 = sv->vertex(ind0);
    7415            0 :                                         if(!nv1)
    7416            0 :                                                 nv1 = sv->vertex(ind1);
    7417              : 
    7418              : #if 1
    7419              :                                         //      create the new edge if it not already exists.
    7420            0 :                                         if( ! m_grid.get_edge(nv0, nv1))
    7421            0 :                                                 m_grid.create_by_cloning(e, EdgeDescriptor(nv0, nv1), e);
    7422              : #else // only for debugging purposes
    7423              : 
    7424              :                                         //                                      if( ! ( m_vrtxAttAccsVrtxArisesFromExpandedEndingCrossingCleft[nv0] || m_vrtxAttAccsVrtxArisesFromExpandedEndingCrossingCleft[nv0] ) )
    7425              :                                         {
    7426              :                                                 //      create the new edge if it not already exists.
    7427              :                                                 if( ! m_grid.get_edge(nv0, nv1))
    7428              :                                                 {
    7429              :                                                         Edge * cloneEdge = * ( m_grid.create_by_cloning(e, EdgeDescriptor(nv0, nv1), e) );
    7430              : 
    7431              :                                                         if( ( m_vrtxAttAccsVrtxArisesFromExpandedEndingCrossingCleft[nv0] || m_vrtxAttAccsVrtxArisesFromExpandedEndingCrossingCleft[nv1] ) )
    7432              :                                                         {
    7433              :                                                                 m_sh.assign_subset(cloneEdge, m_sh.num_subsets());
    7434              :                                                                 UG_LOG("Edge clone from ending crossing cleft new shift vertex" << std::endl);
    7435              : 
    7436              :                                                         }
    7437              :                                                 }
    7438              :                                         }
    7439              :                                         //                                      else
    7440              :                                         //                                      {
    7441              :                                         //                                              UG_LOG("Edge clone from ending crossing cleft new shift vertex" << std::endl);
    7442              :                                         //                                      }
    7443              : 
    7444              :                                         // Ergebnis dieses debug Teils: alle edges, die geclont werden, sind notwendig
    7445              :                                         // auch bei ending crossing clefts
    7446              : #endif
    7447              :                                 }
    7448              :                         }
    7449              :                 }
    7450              :         }
    7451              : 
    7452              :         UG_LOG("Vol enter clone finished " << std::endl);
    7453              : 
    7454              :         //      now we create new faces from selected ones which are connected to
    7455              :         //      inner vertices. This allows to preserve old subsets.
    7456              :         //      Since we have to make sure that we use the right vertices,
    7457              :         //      we have to iterate over the selected volumes and perform all actions on the side-faces
    7458              :         //      of those volumes.
    7459              : 
    7460            0 :         FaceDescriptor fd;
    7461              : 
    7462              : 
    7463            0 :         for(VolumeIterator iter_sv = m_sel.volumes_begin(); iter_sv != m_sel.volumes_end(); ++iter_sv)
    7464              :         {
    7465              :                 Volume* sv = *iter_sv;
    7466              :                 //      check for each face whether it has to be copied.
    7467              : 
    7468            0 :                 UG_LOG("Face descriptor for vol " << CalculateCenter(sv, m_aaPos) << std::endl);
    7469              : 
    7470            0 :                 for(size_t i_face = 0; i_face < sv->num_faces(); ++i_face)
    7471              :                 {
    7472            0 :                         Face* sf = m_grid.get_face(sv, i_face);
    7473              : 
    7474            0 :                         if( m_sel.is_selected(sf))
    7475              :                         {
    7476              :                                 //      check the associated vertices through the volumes aaVrtVecVol attachment.
    7477              :                                 //      If no face between the new vertices already exists, we'll create the new face.
    7478            0 :                                 sv->get_vertex_indices_of_face(locVrtInds, i_face);
    7479            0 :                                 fd.set_num_vertices(sf->num_vertices());
    7480              : 
    7481              :                                 bool containsEndingCrossingCleftVrtx = false;
    7482              : 
    7483            0 :                                 for(size_t i = 0; i < sf->num_vertices(); ++i)
    7484              :                                 {
    7485            0 :                                         Vertex* nVrt = (m_aaVrtVecVol[sv])[locVrtInds[i]];
    7486              : 
    7487            0 :                                         if(nVrt)
    7488            0 :                                                 fd.set_vertex(i, nVrt);
    7489              :                                         else
    7490            0 :                                                 fd.set_vertex(i, sv->vertex(locVrtInds[i]));
    7491              :                                 }
    7492              : 
    7493              : #if 1
    7494              :                                 //      if the new face does not already exist, we'll create it
    7495            0 :                                 if(!m_grid.get_face(fd))
    7496            0 :                                         m_grid.create_by_cloning(sf, fd, sf);
    7497              : #else
    7498              :                                 //      if the new face does not already exist, we'll create it
    7499              :                                 if( ! m_grid.get_face(fd) )
    7500              :                                 {
    7501              :                                         Face * fac = *( m_grid.create_by_cloning(sf, fd, sf) );
    7502              : 
    7503              :                                         bool faceAtEndingCrossingCleft = m_aaMarkFaceWithEndingCrossingCleft[sf];
    7504              : 
    7505              :                                         bool faceTouchingEndingCrossingCleft = m_facAttAccsIfFaceIsSegmLimFaceEndingCrossingCleft[sf];
    7506              : 
    7507              :                                         if( faceAtEndingCrossingCleft || faceTouchingEndingCrossingCleft )
    7508              :                                         {
    7509              :                                                 m_sh.assign_subset( fac, m_sh.num_subsets() );
    7510              :                                                 UG_LOG("Face at ending crossing cleft" << std::endl);
    7511              :                                         }
    7512              :                                 }
    7513              : 
    7514              :                                 // Ergebnis dieses debug Teils: alle faces, die geclont werden, sind notwendig
    7515              :                                 // auch bei ending crossing clefts
    7516              : #endif
    7517              : 
    7518              :                         }
    7519              :                 }
    7520              :         }
    7521              : 
    7522              :         UG_LOG("Face descriptor left" << std::endl);
    7523              : 
    7524              :         //      Expand all faces.
    7525              :         //      Since volumes are replaced on the fly, we have to take care with the iterator.
    7526              :         //      record all new volumes in a vector. This will help to adjust positions later on.
    7527              : 
    7528              :         std::vector<Volume*> newFractureVolumes;
    7529              :         std::vector<IndexType> subsOfNewVolumes;
    7530              : 
    7531              :         // create alternative volumes where there are ending crossing clefts
    7532              : 
    7533              : //      etablishVolumesAtEndingCrossingClefts( std::vector<Volume*> & newFractureVolumes, std::vector<IndexType> & subsOfNewVolumes );
    7534            0 :         if( ! etablishVolumesAtEndingCrossingClefts( newFractureVolumes, subsOfNewVolumes ) )
    7535              :         {
    7536              :                 UG_LOG("unable to establish volumes at ending crossing clefts" << std::endl);
    7537              :                 return false;
    7538              :         }
    7539              : 
    7540              : //      return false;
    7541              : 
    7542            0 :         VolumeDescriptor vd;
    7543              : 
    7544              :         // beim Volumen fängt das Abfangen an, es muss abgefragt werden, ob das Volumen aus
    7545              :         // einem Segment ist, wo bisher falsch expandiert wird
    7546              :         // erst beim Face ab zu fangen ist viel zu spät TODO FIXME
    7547              :         // nicht zu vergessen, die Edges ordentlich sortiert zu sammeln, die zwei endende Vertizes enthalten,
    7548              :         // und dann zu splitten, wenn alle Attachements entfernt sind, dann Neustart anfordern mit neuer Geometrie
    7549              : 
    7550            0 :         for(VolumeIterator iter_sv = m_sel.volumes_begin(); iter_sv != m_sel.volumes_end();)
    7551              :         {
    7552              :                 Volume* sv = *iter_sv;
    7553              :                 ++iter_sv;
    7554              : 
    7555            0 :                 UG_LOG("Volume new creation try at " << CalculateCenter(sv, m_aaPos) << std::endl);
    7556              : 
    7557              :                 bool volHasEndingCrossingCleftFace = m_volAttAccsVolTouchesEndingCrossingCleft[sv];
    7558              : 
    7559              :                 //      now expand the fracture faces of sv to volumes.
    7560            0 :                 for(size_t i_side = 0; i_side < sv->num_sides(); ++i_side)
    7561              :                 {
    7562              :                         //      get the local vertex indices of the side of the volume
    7563            0 :                         sv->get_vertex_indices_of_face(locVrtInds, i_side);
    7564              : 
    7565            0 :                         Face* tFace = m_grid.get_side(sv, i_side);
    7566              : 
    7567            0 :                         if(tFace)
    7568              :                         {
    7569            0 :                                 if( m_aaMarkFaceIsFracB[tFace] ) // && ! m_aaMarkFaceHasUnclosedFracSideB[tFace] )
    7570              :                                 {
    7571              :                                         bool faceIsSegmLimEndCrossCleft = m_facAttAccsIfFaceIsSegmLimFaceEndingCrossingCleft[tFace];
    7572              :                                         bool faceIsEndingCleftCrossFace = m_aaMarkFaceWithEndingCrossingCleft[tFace];
    7573              : 
    7574            0 :                                         bool avoidFace = ( volHasEndingCrossingCleftFace && ( faceIsSegmLimEndCrossCleft || faceIsEndingCleftCrossFace ) );
    7575              : 
    7576              : //                                      for( Face * testFac :  m_d_endingCrossingCleftFaces )
    7577              : //                                      {
    7578              : //                                              if( testFac == tFace )
    7579              : //                                              {
    7580              : //                                                      avoidFace = true;
    7581              : //                                              }
    7582              : //                                      }
    7583              : //
    7584              : //                                      for( Face * testFac :  m_d_crossingNeighboredNotEndingFaces )
    7585              : //                                      {
    7586              : //                                              if( testFac == tFace )
    7587              : //                                              {
    7588              : //                                                      avoidFace = true;
    7589              : //                                              }
    7590              : //                                      }
    7591              : //
    7592              : //                                      for( Face * testFac :  m_d_crossingNeighboredNotEndingFacesCommEdg )
    7593              : //                                      {
    7594              : //                                              if( testFac == tFace )
    7595              : //                                              {
    7596              : //                                                      avoidFace = true;
    7597              : //                                              }
    7598              : //                                      }
    7599              : //
    7600              : //                                      for( Face * testFac :  m_d_notEndingCrossingFacesNotNeighbour )
    7601              : //                                      {
    7602              : //                                              if( testFac == tFace )
    7603              : //                                              {
    7604              : //                                                      avoidFace = true;
    7605              : //                                              }
    7606              : //                                      }
    7607              : 
    7608              : 
    7609              :                                         constexpr bool debugTest = true;
    7610              : 
    7611            0 :                                         if( avoidFace && debugTest )
    7612            0 :                                                 continue;
    7613              : 
    7614            0 :                                         Volume* expVol = nullptr;
    7615              : 
    7616            0 :                                         if(locVrtInds.size() == 3)
    7617              :                                         {
    7618            0 :                                                 size_t iv0 = locVrtInds[0];
    7619            0 :                                                 size_t iv1 = locVrtInds[1];
    7620            0 :                                                 size_t iv2 = locVrtInds[2];
    7621              : 
    7622              :                                                 if(    ( m_aaVrtVecVol[sv] )[iv0]
    7623            0 :                                                         && ( m_aaVrtVecVol[sv] )[iv1]
    7624            0 :                                                         && ( m_aaVrtVecVol[sv] )[iv2]
    7625              :                                                 )
    7626              :                                                 {
    7627              :                                                         //      create a new prism
    7628            0 :                                                         expVol = *m_grid.create<Prism>(
    7629            0 :                                                                                         PrismDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    7630              :                                                                                                                         (m_aaVrtVecVol[sv])[iv2],
    7631              :                                                                                                                         (m_aaVrtVecVol[sv])[iv1],
    7632              :                                                                                                                         (m_aaVrtVecVol[sv])[iv0]));
    7633              :                                                 }
    7634              :                                                 else if(    ( m_aaVrtVecVol[sv] )[iv0]
    7635            0 :                                                                  && ( m_aaVrtVecVol[sv] )[iv1]
    7636              :                                                 )
    7637              :                                                 {
    7638              :                                                         //      create a new Pyramid
    7639            0 :                                                         expVol = *m_grid.create<Pyramid>(
    7640            0 :                                                                                         PyramidDescriptor(sv->vertex(iv0), sv->vertex(iv1),
    7641              :                                                                                                 (m_aaVrtVecVol[sv])[iv1],
    7642              :                                                                                                 (m_aaVrtVecVol[sv])[iv0],
    7643            0 :                                                                                                 sv->vertex(iv2)));
    7644              :                                                 }
    7645              :                                                 else if(    ( m_aaVrtVecVol[sv] )[iv1]
    7646            0 :                                                                  && ( m_aaVrtVecVol[sv] )[iv2]
    7647              :                                                 )
    7648              :                                                 {
    7649              :                                                         //      create a new Pyramid
    7650            0 :                                                         expVol = *m_grid.create<Pyramid>(
    7651            0 :                                                                                         PyramidDescriptor(sv->vertex(iv1), sv->vertex(iv2),
    7652              :                                                                                                 (m_aaVrtVecVol[sv])[iv2],
    7653              :                                                                                                 (m_aaVrtVecVol[sv])[iv1],
    7654            0 :                                                                                                 sv->vertex(iv0)));
    7655              :                                                 }
    7656              :                                                 else if(    (m_aaVrtVecVol[sv])[iv0]
    7657            0 :                                                                  && (m_aaVrtVecVol[sv])[iv2]
    7658              :                                                 )
    7659              :                                                 {
    7660              :                                                         //      create a new Pyramid
    7661            0 :                                                         expVol = *m_grid.create<Pyramid>(
    7662            0 :                                                                                         PyramidDescriptor(sv->vertex(iv2), sv->vertex(iv0),
    7663              :                                                                                                 (m_aaVrtVecVol[sv])[iv0],
    7664              :                                                                                                 (m_aaVrtVecVol[sv])[iv2],
    7665            0 :                                                                                                 sv->vertex(iv1)));
    7666              :                                                 }
    7667            0 :                                                 else if( ( m_aaVrtVecVol[sv])[iv0] )
    7668              :                                                 {
    7669              :                                                         //      create a new Tetrahedron
    7670            0 :                                                         expVol = *m_grid.create<Tetrahedron>(
    7671            0 :                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    7672              :                                                                                                                                  (m_aaVrtVecVol[sv])[iv0]));
    7673              :                                                 }
    7674            0 :                                                 else if( ( m_aaVrtVecVol[sv])[iv1] )
    7675              :                                                 {
    7676              :                                                         //      create a new Tetrahedron
    7677            0 :                                                         expVol = *m_grid.create<Tetrahedron>(
    7678            0 :                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    7679              :                                                                                                                                  (m_aaVrtVecVol[sv])[iv1]));
    7680              :                                                 }
    7681            0 :                                                 else if( ( m_aaVrtVecVol[sv])[iv2] )
    7682              :                                                 {
    7683              :                                                         //      create a new Tetrahedron
    7684            0 :                                                         expVol = *m_grid.create<Tetrahedron>(
    7685            0 :                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    7686              :                                                                                                                                  (m_aaVrtVecVol[sv])[iv2]));
    7687              :                                                 }
    7688              :                                                 else
    7689              :                                                 {
    7690              :                                                         //      Text from SR, still similar:
    7691              :                                                         //  this code-block should never be entered. If it is entered then
    7692              :                                                         //      we either selected the wrong faces (this shouldn't happen), or there
    7693              :                                                         //      are selected faces, which have fracture-boundary-vertices only.
    7694              :                                                         //      This is the same is if inner fracture edges exists, which are
    7695              :                                                         //      connected to two boundary vertices.
    7696              :                                                         //      Since we tried to remove those edges above, something went wrong.
    7697              :                                                         //      remove the temporary attachments and throw an error
    7698              : 
    7699              :                                                         UG_LOG("Tetraeder Fehlt eine Loesung " << std::endl);
    7700              : #if 1
    7701            0 :                                                         detachMarkers();
    7702            0 :                                                         throw(UGError("Error in ExpandFractures3d Arte Stasi. Implementation Error."));
    7703              :                                                         return false;
    7704              : #endif
    7705              :                                                 }
    7706              :                                         }
    7707            0 :                                         else if ( locVrtInds.size() == 4 )
    7708              :                                         {
    7709              :                                                 // newly implemented by Markus to test with Hexahedrons, not really working.....
    7710              : 
    7711            0 :                                                 size_t iv0 = locVrtInds[0];
    7712            0 :                                                 size_t iv1 = locVrtInds[1];
    7713            0 :                                                 size_t iv2 = locVrtInds[2];
    7714            0 :                                                 size_t iv3 = locVrtInds[3];
    7715              : 
    7716              :                                                 if(    ( m_aaVrtVecVol[sv] )[iv0]
    7717            0 :                                                         && ( m_aaVrtVecVol[sv] )[iv1]
    7718            0 :                                                         && ( m_aaVrtVecVol[sv] )[iv2]
    7719            0 :                                                         && ( m_aaVrtVecVol[sv] )[iv3]
    7720              :                                                 )
    7721              :                                                 {
    7722              :                                                         //      create a new prism
    7723            0 :                                                         expVol = *m_grid.create<Hexahedron>(
    7724            0 :                                                                                                 HexahedronDescriptor(
    7725            0 :                                                                                                                         sv->vertex(iv3), sv->vertex(iv2),
    7726            0 :                                                                                                                         sv->vertex(iv1), sv->vertex(iv0),
    7727              :                                                                                                                         (m_aaVrtVecVol[sv])[iv3],
    7728              :                                                                                                                         (m_aaVrtVecVol[sv])[iv2],
    7729              :                                                                                                                         (m_aaVrtVecVol[sv])[iv1],
    7730              :                                                                                                                         (m_aaVrtVecVol[sv])[iv0]
    7731              :                                                                                                                         )
    7732              :                                                                                                                 );
    7733              : 
    7734              : //                                                      m_sh.assign_subset(expVol, m_fracInfosBySubset.at(m_sh.get_subset_index(tFace)).newSubsetIndex);
    7735              : //
    7736              : //                                                      return true;
    7737              :                                                 }
    7738              :                                                 else if(    ( m_aaVrtVecVol[sv] )[iv0]
    7739            0 :                                                                  && ( m_aaVrtVecVol[sv] )[iv1]
    7740              : 
    7741              :                                                 )
    7742              :                                                 {
    7743              :                                                         //      create a new prism
    7744              :                                                         //      create a new prism
    7745              : //                                                      expVol = *m_grid.create<Prism>(
    7746              : //                                                                                      PrismDescriptor(sv->vertex(iv3),sv->vertex(iv2), sv->vertex(iv1),
    7747              : //                                                                                                                      sv->vertex(iv0),
    7748              : //                                                                                                                      (m_aaVrtVecVol[sv])[iv1],
    7749              : //                                                                                                                      (m_aaVrtVecVol[sv])[iv0])
    7750              : //                                                                                                                      );
    7751              :                                                         //      create a new Prism
    7752              :                                                         ///     only used to initialize a prism. for all other tasks you should use VolumeDescripor.
    7753              :                                                         /**
    7754              :                                                          * please be sure to pass the vertices in the correct order:
    7755              :                                                          * v1, v2, v3: bottom-vertices in counterclockwise order (if viewed from the top).
    7756              :                                                          * v4, v5, v6: top-vertices in counterclockwise order (if viewed from the top).
    7757              :                                                          *              PrismDescriptor(Vertex* v1, Vertex* v2, Vertex* v3,
    7758              :                                                 Vertex* v4, Vertex* v5, Vertex* v6);
    7759              :                                                          *
    7760              :                                                          */
    7761            0 :                                                         expVol = *m_grid.create<Prism>(
    7762            0 :                                                                                         PrismDescriptor( (m_aaVrtVecVol[sv])[iv0],
    7763            0 :                                                                                                         sv->vertex(iv0), sv->vertex(iv3),
    7764            0 :                                                                                                         (m_aaVrtVecVol[sv])[iv1], sv->vertex(iv1), sv->vertex(iv2)
    7765              :                                                                                                 )
    7766              :                                                                                                 );
    7767              : 
    7768              :                                                         UG_LOG("PRISM 0 1 " << std::endl);
    7769              :                                                 }
    7770              :                                                 else if(    ( m_aaVrtVecVol[sv] )[iv0]
    7771            0 :                                                                  && ( m_aaVrtVecVol[sv] )[iv2]
    7772              :                                                 )
    7773              :                                                 {
    7774              :                                                         UG_LOG("PRISM 0 2 " << std::endl);
    7775            0 :                                                         expVol = *m_grid.create<Prism>(
    7776            0 :                                                                                         PrismDescriptor( (m_aaVrtVecVol[sv])[iv0],
    7777            0 :                                                                                                         sv->vertex(iv0), sv->vertex(iv3),
    7778            0 :                                                                                                         sv->vertex(iv2), (m_aaVrtVecVol[sv])[iv2], sv->vertex(iv1)
    7779              :                                                                                                 )
    7780              :                                                                                                 );
    7781              : 
    7782              : //                                                      m_sh.assign_subset(expVol, m_sh.num_subsets());
    7783              : //                                                      m_sh.assign_subset( sv->vertex(iv0), m_sh.num_subsets());
    7784              : //                                                      m_sh.assign_subset( sv->vertex(iv1), m_sh.num_subsets());
    7785              : //                                                      m_sh.assign_subset( sv->vertex(iv2), m_sh.num_subsets());
    7786              : //                                                      m_sh.assign_subset( sv->vertex(iv3), m_sh.num_subsets());
    7787              : //                                                      m_sh.assign_subset( (m_aaVrtVecVol[sv])[iv0], m_sh.num_subsets());
    7788              : //                                                      m_sh.assign_subset( (m_aaVrtVecVol[sv])[iv2], m_sh.num_subsets());
    7789              : 
    7790              : 
    7791              :                                                 }
    7792              :                                                 else if(    ( m_aaVrtVecVol[sv] )[iv0]
    7793            0 :                                                                  && ( m_aaVrtVecVol[sv] )[iv3]
    7794              :                                                 )
    7795              :                                                 {
    7796              :                                                         UG_LOG("PRISM 0 3 " << std::endl);
    7797              : 
    7798              :                                                 }
    7799              :                                                 else if(    ( m_aaVrtVecVol[sv] )[iv1]
    7800            0 :                                                                  && ( m_aaVrtVecVol[sv] )[iv2]
    7801              :                                                 )
    7802              :                                                 {
    7803              : 
    7804              :                                                         UG_LOG("PRISM 1 2 " << std::endl);
    7805              : 
    7806              :                                                 }
    7807              :                                                 else if(    ( m_aaVrtVecVol[sv] )[iv2]
    7808            0 :                                                                  && ( m_aaVrtVecVol[sv] )[iv3]
    7809              :                                                 )
    7810              :                                                 {
    7811              :                                                         UG_LOG("PRISM 2 3 " << std::endl);
    7812              : 
    7813              :                                                 }
    7814              : 
    7815              : 
    7816              : 
    7817              :                                         }
    7818              :                                         else
    7819              :                                         {
    7820              :                                                 //      traditionally only tetrahedrons are supported. This section thus raises an error
    7821              :                                                 // Markus tries to implement also Hexahedra
    7822              : //                                                      grid.detach_from_vertices(aVrtVec);
    7823              : //                                                      grid.detach_from_volumes(aVrtVec);
    7824              : //                                                      grid.detach_from_vertices(aAdjMarker);
    7825              : //                                                      grid.detach_from_edges(aAdjMarker);
    7826            0 :                                                 detachMarkers();
    7827            0 :                                                 throw(UGError("Incomplete implementation error in ExpandFractures3d Arte: Only tetrahedrons are supported in the current implementation, and hexahedra are in development."));
    7828              :                                                 return false;
    7829              :                                         }
    7830              : 
    7831            0 :                                         if(expVol)
    7832              :                                         {
    7833              : 
    7834            0 :                                                 IndexType newSubs = m_fracInfosBySubset.at(m_sh.get_subset_index(tFace)).newSubsetIndex;
    7835              : 
    7836            0 :                                                 subsOfNewVolumes.push_back( newSubs );
    7837              : 
    7838              : //                                              m_sh.assign_subset(expVol, m_fracInfosBySubset.at(m_sh.get_subset_index(tFace)).newSubsetIndex);
    7839            0 :                                                 m_sh.assign_subset(expVol, newSubs);
    7840              : 
    7841            0 :                                                 newFractureVolumes.push_back(expVol);
    7842              : 
    7843              :                                                 // TODO FIXME irgendwie hier muss die Infosammlung für die Diamenten auch stattfinden
    7844              : 
    7845              :                                                 // check if contains a crossing point
    7846              : 
    7847              :                                                 IndexType constexpr maxVolVrtxNum = 3;  // restricts algo to tetrahedral based grids
    7848              : 
    7849              : #if 1
    7850              : //                                              std::vector<VrtxPair> oldShiftVrtcs;
    7851              : 
    7852            0 :                                                 for( auto const & crossVrtx : m_vrtcsCrossingPts )
    7853              :                                                 {
    7854            0 :                                                         for( IndexType i = 0; i < maxVolVrtxNum; i++ )
    7855              :                                                         {
    7856            0 :                                                                 IndexType iv = locVrtInds[i];
    7857            0 :                                                                 Vertex * oldVrt = sv->vertex(iv);
    7858              : 
    7859            0 :                                                                 if( oldVrt == crossVrtx )
    7860              :                                                                 {
    7861            0 :                                                                         Vertex * shiVrt = ( m_aaVrtVecVol[sv] )[iv];
    7862              : 
    7863            0 :                                                                         if( shiVrt )
    7864              :                                                                         {
    7865            0 :                                                                                 Vertex * oldVrt = sv->vertex(iv);
    7866              :                                                                                 VrtxPair osv( oldVrt, shiVrt );
    7867              :                                                                                 VolManifVrtxCombi vmvc( expVol, tFace, osv, newSubs );
    7868              : 
    7869            0 :                                                                                 m_vecVolManifVrtxCombiToShrink4Diams.push_back(vmvc);
    7870              :                                                                         }
    7871              :                                                                 }
    7872              :                                                         }
    7873              :                                                 }
    7874              : 
    7875              : //                                              if( oldShiftVrtcs.size() > 0 )
    7876              : //                                              {
    7877              : //                                              }
    7878              : 
    7879              : #else
    7880              : 
    7881              :                                                 bool containsCrossVrtx = false;
    7882              : 
    7883              :                                                 for( auto const & crossVrtx : m_vrtcsCrossingPts )
    7884              :                                                 {
    7885              :                                                         for( IndexType i = 0; i < maxVolVrtxNum; i++ )
    7886              :                                                         {
    7887              :                                                                 IndexType iv = locVrtInds[i];
    7888              :                                                                 Vertex * oldVrt = sv->vertex(iv);
    7889              : 
    7890              :                                                                 if( oldVrt == crossVrtx )
    7891              :                                                                 {
    7892              :                                                                         containsCrossVrtx = true;
    7893              :                                                                         break;
    7894              :                                                                 }
    7895              :                                                         }
    7896              : 
    7897              :                                                         if( containsCrossVrtx )
    7898              :                                                                 break;
    7899              :                                                 }
    7900              : 
    7901              :                                                 if( containsCrossVrtx )
    7902              :                                                 {
    7903              :                                                         std::vector<VrtxPair> oldShiftVrtcs;
    7904              : 
    7905              :                                                         for( IndexType i = 0; i < maxVolVrtxNum; i++ )
    7906              :                                                         {
    7907              :                                                                 IndexType iv = locVrtInds[i];
    7908              : 
    7909              :                                                                 Vertex * shiVrt = ( m_aaVrtVecVol[sv] )[iv];
    7910              : 
    7911              :                                                                 if( shiVrt )
    7912              :                                                                 {
    7913              :                                                                         Vertex * oldVrt = sv->vertex(iv);
    7914              :                                                                         VrtxPair cv( oldVrt, shiVrt );
    7915              :                                                                         oldShiftVrtcs.push_back(cv);
    7916              :                                                                 }
    7917              :                                                         }
    7918              : 
    7919              :                                                         VolManifVrtxCombi vmvc( expVol, tFace, oldShiftVrtcs, newSubs );
    7920              : 
    7921              :                                                         m_vecVolManifVrtxCombiToShrink4Diams.push_back(vmvc);
    7922              :                                                 }
    7923              : 
    7924              : #endif
    7925              : 
    7926              :                                         }
    7927              :                                 }
    7928              :                         }
    7929              :                 }
    7930              : 
    7931              :                 //      now set up a new volume descriptor and replace the volume.
    7932            0 :                 if(vd.num_vertices() != sv->num_vertices())
    7933            0 :                         vd.set_num_vertices(sv->num_vertices());
    7934              : 
    7935            0 :                 for(size_t i_vrt = 0; i_vrt < sv->num_vertices(); ++i_vrt)
    7936              :                 {
    7937            0 :                         if( (m_aaVrtVecVol[sv])[i_vrt] )
    7938            0 :                                 vd.set_vertex(i_vrt, (m_aaVrtVecVol[sv])[i_vrt]);
    7939              :                         else
    7940            0 :                                 vd.set_vertex(i_vrt, sv->vertex(i_vrt));
    7941              :                 }
    7942              : 
    7943            0 :                 m_grid.create_by_cloning(sv, vd, sv);
    7944            0 :                 m_grid.erase(sv);
    7945              :         }
    7946              : 
    7947              :         UG_LOG("Volumes erzeugt " << std::endl);
    7948              : 
    7949              : //      return false;
    7950              : 
    7951              : 
    7952              : 
    7953              : 
    7954              :         //      we have to clean up unused faces and edges.
    7955              :         //      note that all selected edges with mark 0 may safley be deleted. - warum?
    7956            0 :         for(EdgeIterator iter = m_sel.begin<Edge>(); iter!= m_sel.end<Edge>();)
    7957              :         {
    7958              :                 //      take care of the iterator
    7959              :                 Edge* e = *iter;
    7960              :                 ++iter;
    7961              : 
    7962            0 :                 if( m_aaMarkEdgeVFP[e].getNumberFracEdgesInVertex() == 0 )
    7963            0 :                         m_grid.erase(e);
    7964              :         }
    7965              : 
    7966              :         //      make sure that no unused faces linger around (This should never happen!)
    7967              :         bool foundUnusedFaces = false;
    7968              : 
    7969            0 :         for(FaceIterator iter = m_sel.begin<Face>(); iter != m_sel.end<Face>();)
    7970              :         {
    7971              :                 Face* f = *iter;
    7972              :                 ++iter;
    7973              : 
    7974              : //              if( m_aaMarkFaceHasUnclosedFracSideB[f] )
    7975              : //              {
    7976              : //                      UG_LOG("want to delete unclosed frac face " << std::endl);
    7977              : //                      // todo fixme XXXXXXXXXXXXXXXXXX
    7978              : //                      //return false;
    7979              : //              }
    7980              : 
    7981            0 :                 if( ! m_aaMarkFaceIsFracB[f] )
    7982              :                 {
    7983              :                         foundUnusedFaces = true;
    7984            0 :                         m_grid.erase(f);
    7985              :                 }
    7986              :         }
    7987              : 
    7988            0 :         if(foundUnusedFaces)
    7989              :         {
    7990              :                 UG_LOG("WARNING in ExpandFractures3D Arte: Unused faces encountered during cleanup. Removing them...\n");
    7991              :         }
    7992              : 
    7993            0 :         if( subsOfNewVolumes.size() != newFractureVolumes.size() )
    7994              :         {
    7995            0 :                 UG_THROW("andere zahl neue volumes als subdoms " << std::endl);
    7996              :         }
    7997              : 
    7998              : 
    7999              : //      return true;
    8000              : 
    8001              : 
    8002              :         IndexType nfn = 0;
    8003              : 
    8004            0 :         for( auto const & nf : newFractureVolumes )
    8005              :         {
    8006            0 :                 for(size_t iFace = 0; iFace < nf->num_faces(); ++iFace)
    8007              :                 {
    8008            0 :                         Face * fac = m_grid.get_face(nf, iFace);
    8009              : 
    8010            0 :                         m_sh.assign_subset( fac, subsOfNewVolumes[nfn] );
    8011              : 
    8012              :                 }
    8013              : 
    8014            0 :                 for(size_t iEdge = 0; iEdge < nf->num_edges(); ++iEdge)
    8015              :                 {
    8016            0 :                         Edge* edg = m_grid.get_edge(nf, iEdge);
    8017              : 
    8018            0 :                         m_sh.assign_subset( edg, subsOfNewVolumes[nfn] );
    8019              : 
    8020              :                 }
    8021              : 
    8022            0 :                 for( size_t iVrt = 0; iVrt < nf->num_vertices(); iVrt++ )
    8023              :                 {
    8024            0 :                         Vertex * vrt = nf->vertex(iVrt);
    8025              : 
    8026            0 :                         m_sh.assign_subset( vrt, subsOfNewVolumes[nfn] );
    8027              :                 }
    8028              : 
    8029            0 :                 nfn++;
    8030              :         }
    8031              : 
    8032            0 :         for( EndingCrossingFractureSegmentInfo const & ecfsi : m_vecEndCrossFractSegmInfo )
    8033              :         {
    8034              :                 Face * hiddenCutFracFace = ecfsi.spuckHiddenCutFractManifEl();
    8035              : 
    8036              :                 IndexType subsECC = ecfsi.spuckSudoFractEnding();
    8037              : 
    8038            0 :                 m_sh.assign_subset( hiddenCutFracFace, subsECC );
    8039              : 
    8040            0 :                 for(size_t iEdge = 0; iEdge < hiddenCutFracFace->num_edges(); ++iEdge)
    8041              :                 {
    8042            0 :                         Edge* edg = m_grid.get_edge(hiddenCutFracFace, iEdge);
    8043              : 
    8044            0 :                         m_sh.assign_subset( edg, subsECC );
    8045              : 
    8046              :                 }
    8047              : 
    8048            0 :                 for( size_t iVrt = 0; iVrt < hiddenCutFracFace->num_vertices(); iVrt++ )
    8049              :                 {
    8050            0 :                         Vertex * vrt = hiddenCutFracFace->vertex(iVrt);
    8051              : 
    8052            0 :                         m_sh.assign_subset( vrt, subsECC );
    8053              :                 }
    8054              : 
    8055              :         }
    8056              : 
    8057              : 
    8058              :         return true;
    8059            0 : }
    8060              : 
    8061            0 : ArteExpandFracs3D::IndexType ArteExpandFracs3D::deleteEndingCrossingCleftOrigFacs()
    8062              : {
    8063              : 
    8064              :         IndexType numOfDelSegs = 0;
    8065              : 
    8066            0 :         for( EndingCrossingFractureSegmentInfo const & ecfsi : m_vecEndCrossFractSegmInfo )
    8067              :         {
    8068              :                 Vertex * vrt = ecfsi.spuckUnclosedVrtx();
    8069              : 
    8070              :                 Edge * directionEdge = ecfsi.spuckLowdimElmShiftDirection();
    8071              : 
    8072              :                 Face * oldFractFacCut = ecfsi.spuckEndingFractManifCutting();
    8073              : 
    8074              :                 std::vector<Face*> vecOldFractFacNotCut = ecfsi.spuckVecEndingFractManifNotCutting();
    8075              : 
    8076              : //              Edge * commonEdge = nullptr;
    8077              : 
    8078              :                 std::vector<Edge*> innerEdges;
    8079              : 
    8080            0 :                 for( Face * oldFractFacNotCut : vecOldFractFacNotCut )
    8081              :                 {
    8082              : //                      for(size_t iEdge = 0; iEdge < oldFractFacCut->num_edges(); ++iEdge)
    8083              : //                      {
    8084              : //                              Edge* edgC = m_grid.get_edge(oldFractFacCut, iEdge);
    8085              : 
    8086            0 :                         for(size_t iEdge = 0; iEdge < oldFractFacNotCut->num_edges(); ++iEdge)
    8087              :                         {
    8088            0 :                                 Edge* edgN = m_grid.get_edge(oldFractFacNotCut, iEdge);
    8089              : 
    8090            0 :                                 if( edgN != directionEdge && EdgeContains(edgN, vrt) )
    8091              :                                         addElem(innerEdges, edgN);
    8092              : //                                      if( edgC == edgN )
    8093              : //                                      {
    8094              : //                                              commonEdge = edgC;
    8095              : //                                              break;
    8096              : //                                      }
    8097              : 
    8098              :                         }
    8099              : //                              if( commonEdge )
    8100              : //                                      break;
    8101              : //
    8102              : //                      }
    8103              :                 }
    8104              : 
    8105            0 :                 if( oldFractFacCut )
    8106            0 :                         m_grid.erase(oldFractFacCut);
    8107              : 
    8108            0 :                 for( Face * oldFractFacNotCut : vecOldFractFacNotCut )
    8109              :                 {
    8110            0 :                         if( oldFractFacNotCut )
    8111            0 :                                 m_grid.erase(oldFractFacNotCut);
    8112              :                 }
    8113              : 
    8114            0 :                 if( directionEdge )
    8115            0 :                         m_grid.erase(directionEdge);
    8116              : 
    8117            0 :                 for( Edge * iE : innerEdges )
    8118              :                 {
    8119            0 :                         if( iE )
    8120              :                         {
    8121            0 :                                 m_grid.erase(iE);
    8122              : //                              m_sh.assign_subset( iE, m_sh.num_subsets());
    8123              :                         }
    8124              :                 }
    8125              : 
    8126            0 :                 numOfDelSegs++;
    8127            0 :         }
    8128              : 
    8129            0 :         return numOfDelSegs;
    8130              : }
    8131              : 
    8132              : ////////////////////////////////////////////////////////////
    8133              : 
    8134            0 : bool ArteExpandFracs3D::etablishVolumesAtEndingCrossingClefts( std::vector<Volume*> & newFractureVolumes, std::vector<IndexType> & subsOfNewVolumes )
    8135              : {
    8136              : 
    8137            0 :         for( EndingCrossingFractureSegmentInfo & ecfsi : m_vecEndCrossFractSegmInfo )
    8138              :         {
    8139              :                 Vertex * baseVrtx = ecfsi.spuckUnclosedVrtx();
    8140              : 
    8141              :                 Vertex * shiftVrtx = ecfsi.spuckShiftVrtx();
    8142              : 
    8143              :                 Edge * cutEdge = ecfsi.spuckOldLowDimElCut();
    8144              : 
    8145              :                 Vertex * secondVrtxCutEdge = nullptr;
    8146              : 
    8147            0 :                 if( cutEdge->vertex(0) == baseVrtx )
    8148              :                 {
    8149            0 :                         secondVrtxCutEdge = cutEdge->vertex(1);
    8150              :                 }
    8151            0 :                 else if( cutEdge->vertex(1) == baseVrtx )
    8152              :                 {
    8153            0 :                         secondVrtxCutEdge = cutEdge->vertex(0);
    8154              :                 }
    8155              :                 else
    8156              :                 {
    8157              :                         UG_LOG("no second vertex of cut edge " << std::endl);
    8158            0 :                         UG_THROW("no second vertex of cut edge " << std::endl);
    8159              :                         return false;
    8160              :                 }
    8161              : 
    8162            0 :                 Edge * divisionEdge = *m_grid.create<RegularEdge>( EdgeDescriptor( secondVrtxCutEdge, shiftVrtx ) );
    8163              : 
    8164              :                 IndexType subsetECC = ecfsi.spuckSudoFractEnding();
    8165              : 
    8166              : //              m_sh.assign_subset(divisionEdge, m_sh.num_subsets());
    8167            0 :                 m_sh.assign_subset(divisionEdge, subsetECC);
    8168              : 
    8169            0 :                 Face * hiddenCutFracFace = *m_grid.create<Triangle>(TriangleDescriptor( baseVrtx, shiftVrtx, secondVrtxCutEdge ));
    8170              : 
    8171              : //              m_sh.assign_subset(hiddenCutFracFace, m_sh.num_subsets());
    8172            0 :                 m_sh.assign_subset(hiddenCutFracFace, subsetECC);
    8173              : 
    8174            0 :                 IndexType subsNewFacesEdges = m_sh.get_subset_index(hiddenCutFracFace);
    8175              : 
    8176            0 :                 for(size_t iEdge = 0; iEdge < hiddenCutFracFace->num_edges(); ++iEdge)
    8177              :                 {
    8178            0 :                         Edge* edg = m_grid.get_edge(hiddenCutFracFace, iEdge);
    8179              : 
    8180            0 :                         m_sh.assign_subset( edg, subsNewFacesEdges );
    8181            0 :                         UG_LOG("HEDGE CENTER " << CalculateCenter( edg, m_aaPos ) << std::endl );
    8182              : 
    8183            0 :                         UG_LOG("HEdge subdom " << m_sh.get_subset_index(edg) << std::endl );
    8184              : 
    8185              :                 }
    8186              : 
    8187              :                 if( ! ecfsi.schluckHiddenCutFractManifEl( hiddenCutFracFace ))
    8188              :                 {
    8189              :                         UG_LOG("hidden cut face Problem" << std::endl);
    8190            0 :                         UG_THROW("hidden cut face Problem" << std::endl);
    8191              :                 }
    8192              : 
    8193              :                 Face * endingFractFacCutting = ecfsi.spuckEndingFractManifCutting();
    8194              : 
    8195              :                 IndexType const triangVrtxNum = 3;
    8196              : 
    8197            0 :                 if( endingFractFacCutting->num_vertices() != triangVrtxNum )
    8198              :                 {
    8199              :                         UG_LOG("only triangles allowed " << std::endl);
    8200            0 :                         UG_THROW("only triangles allowed " << std::endl);
    8201              :                 }
    8202              : 
    8203              : 
    8204              :                 IndexType foundNotTouchVrtx = 0;
    8205              : 
    8206              :                 Vertex * notTouchingVrtx = nullptr;
    8207              : 
    8208              : 
    8209              :                 // figure out that vertex of the ending fracture faces that is not touching the crossing not ending cleft
    8210            0 :                 for( IndexType vrtIndx = 0; vrtIndx < triangVrtxNum; vrtIndx++ )
    8211              :                 {
    8212            0 :                         Vertex * testVrt = endingFractFacCutting->vertex(vrtIndx);
    8213              : 
    8214            0 :                         if( ! EdgeContains( cutEdge, testVrt ) )
    8215              :                         {
    8216            0 :                                 foundNotTouchVrtx++;
    8217              :                                 notTouchingVrtx = testVrt;
    8218              :                         }
    8219              :                 }
    8220              : 
    8221            0 :                 if( foundNotTouchVrtx != 1 || ! notTouchingVrtx  )
    8222              :                 {
    8223              :                         UG_LOG("not touching vertex not found " << std::endl);
    8224            0 :                         UG_THROW("not touching vertex not found " << std::endl);
    8225              :                 }
    8226              : 
    8227              :                 // replace the face that touches with an edge
    8228            0 :                 Face * replaceEndingFractCutFac = *m_grid.create<Triangle>(TriangleDescriptor( shiftVrtx, secondVrtxCutEdge, notTouchingVrtx ));
    8229              : 
    8230              : //              m_sh.assign_subset( replaceEndingFractCutFac, m_sh.num_subsets() );
    8231            0 :                 m_sh.assign_subset( replaceEndingFractCutFac, subsetECC );
    8232              : 
    8233            0 :                 IndexType subsNewFacesEdgesC = m_sh.get_subset_index(replaceEndingFractCutFac);
    8234              : 
    8235              :                 UG_LOG("EDGE NUMBER CCS CC " << replaceEndingFractCutFac->num_edges() << std::endl);
    8236              : 
    8237            0 :                 for(size_t iEdge = 0; iEdge < replaceEndingFractCutFac->num_edges(); ++iEdge)
    8238              :                 {
    8239            0 :                         Edge* edg = m_grid.get_edge(replaceEndingFractCutFac, iEdge);
    8240              : 
    8241            0 :                         m_sh.assign_subset( edg, subsNewFacesEdgesC );
    8242            0 :                         UG_LOG("EDGE CENTER " << CalculateCenter( edg, m_aaPos ) << std::endl );
    8243              : 
    8244            0 :                         UG_LOG("Edge subdom " << m_sh.get_subset_index(edg) << std::endl );
    8245              : 
    8246              :                 }
    8247              : 
    8248              : //              // replace the face that has only the base vertex common, if existing
    8249              : //              Face * endingFractFacNotCutting = ecfsi.spuckEndingFractManifNotCutting();
    8250              : //
    8251            0 :                 for( Face * const & endingFractFacNotCutting : ecfsi.spuckVecEndingFractManifNotCutting() )
    8252              :                 {
    8253            0 :                         if( endingFractFacNotCutting )
    8254              :                         {
    8255              : 
    8256            0 :                                 if( endingFractFacNotCutting->num_vertices() != triangVrtxNum )
    8257              :                                 {
    8258              :                                         UG_LOG("only triangles allowed NC" << std::endl);
    8259            0 :                                         UG_THROW("only triangles allowed NC" << std::endl);
    8260              :                                 }
    8261              : 
    8262              :                                 std::vector<Vertex*> vrtcsNotBase;
    8263              : 
    8264              :                                 // figure out those vertices which are not the basis vertex
    8265            0 :                                 for( IndexType vrtIndx = 0; vrtIndx < triangVrtxNum; vrtIndx++ )
    8266              :                                 {
    8267            0 :                                         Vertex * testVrt = endingFractFacNotCutting->vertex(vrtIndx);
    8268              : 
    8269            0 :                                         if( testVrt != baseVrtx )
    8270            0 :                                                 vrtcsNotBase.push_back(testVrt);
    8271              :                                 }
    8272              : 
    8273            0 :                                 if( vrtcsNotBase.size() != 2 )
    8274              :                                 {
    8275              :                                         UG_LOG("strange number vertices " << vrtcsNotBase.size() << std::endl);
    8276            0 :                                         UG_THROW("strange number vertices " << vrtcsNotBase.size() << std::endl);
    8277              :                                 }
    8278              : 
    8279            0 :                                 Face * replaceEndingFractNotCutFac = *m_grid.create<Triangle>(TriangleDescriptor( shiftVrtx, vrtcsNotBase[0], vrtcsNotBase[1] ));
    8280              : 
    8281              :         //                      m_sh.assign_subset( replaceEndingFractNotCutFac, m_sh.num_subsets() );
    8282            0 :                                 m_sh.assign_subset( replaceEndingFractNotCutFac, subsetECC );
    8283              : 
    8284            0 :                                 IndexType subsNewFacesEdges = m_sh.get_subset_index(replaceEndingFractNotCutFac);
    8285              : 
    8286              :                                 UG_LOG("EDGE NUMBER CCS " << replaceEndingFractNotCutFac->num_edges() << std::endl);
    8287              : 
    8288            0 :                                 for(size_t iEdge = 0; iEdge < replaceEndingFractNotCutFac->num_edges(); ++iEdge)
    8289              :                                 {
    8290            0 :                                         Edge* edg = m_grid.get_edge(replaceEndingFractNotCutFac, iEdge);
    8291              : 
    8292            0 :                                         m_sh.assign_subset( edg, subsNewFacesEdges );
    8293              : 
    8294            0 :                                         UG_LOG("EDGE CENTER " << CalculateCenter( edg, m_aaPos ) << std::endl );
    8295              : 
    8296            0 :                                         UG_LOG("Edge subdom " << m_sh.get_subset_index(edg) << std::endl );
    8297              : 
    8298              :                                 }
    8299              : 
    8300            0 :                         }
    8301              : 
    8302            0 :                 }
    8303              : 
    8304              : //              for(VolumeIterator iter_sv = m_sel.volumes_begin(); iter_sv != m_sel.volumes_end();)
    8305            0 :                 for( Volume * const & sv : ecfsi.spuckVecFulldimEl() )
    8306              :                 {
    8307              : 
    8308            0 :                         UG_LOG("CEC Volume new creation try at " << CalculateCenter(sv, m_aaPos) << std::endl);
    8309              : 
    8310            0 :                         bool volHasEndingCrossingCleftFace = m_volAttAccsVolTouchesEndingCrossingCleft[sv];
    8311              : 
    8312              :                         // should be true!
    8313              : 
    8314            0 :                         if( ! volHasEndingCrossingCleftFace )
    8315              :                         {
    8316              :                                 UG_LOG("Was ist da los, ending cleft und doch nicht " << std::endl);
    8317            0 :                                 UG_THROW("Was ist da los, ending cleft und doch nicht " << std::endl);
    8318              :                         }
    8319              : 
    8320              :                         // check if volume contains the base vertex
    8321              : 
    8322            0 :                         if( ! VolumeContains(sv, baseVrtx))
    8323              :                         {
    8324              :                                 UG_LOG("VOlume ausdehenen ECC ohne base vertex " << std::endl);
    8325            0 :                                 UG_THROW("VOlume ausdehenen ECC ohne base vertex " << std::endl);
    8326              :                         }
    8327              : 
    8328              :                         //      now expand the fracture faces of sv to volumes.
    8329            0 :                         for(size_t i_side = 0; i_side < sv->num_sides(); ++i_side)
    8330              :                         {
    8331              :                                 //      holds local side vertex indices
    8332              :                                 std::vector<size_t>       locVrtInds;
    8333              : 
    8334              :                                 //      get the local vertex indices of the side of the volume
    8335            0 :                                 sv->get_vertex_indices_of_face(locVrtInds, i_side);
    8336              : 
    8337            0 :                                 Face* tFace = m_grid.get_side(sv, i_side);
    8338              : 
    8339            0 :                                 if(tFace)
    8340              :                                 {
    8341            0 :                                         if( m_aaMarkFaceIsFracB[tFace] )
    8342              :                                         {
    8343              :                                                 bool faceIsSegmLimEndCrossCleft = m_facAttAccsIfFaceIsSegmLimFaceEndingCrossingCleft[tFace];
    8344              :                                                 bool faceIsEndingCleftCrossFace = m_aaMarkFaceWithEndingCrossingCleft[tFace];
    8345              : 
    8346              :                                                 UG_LOG("Volumenerzeugung Versuch ECC Anfang" << std::endl);
    8347              : 
    8348            0 :                                                 Volume* expVol = nullptr;
    8349              : 
    8350            0 :                                                 Volume* expVolTwo = nullptr;
    8351              : 
    8352              : 
    8353            0 :                                                 if(locVrtInds.size() == 3)
    8354              :                                                 {
    8355            0 :                                                         size_t iv0 = locVrtInds[0];
    8356            0 :                                                         size_t iv1 = locVrtInds[1];
    8357            0 :                                                         size_t iv2 = locVrtInds[2];
    8358              : 
    8359              : //                                                      Vertex * vrtxOne = ( m_aaVrtVecVol[sv] )[iv0];
    8360              : //                                                      Vertex * vrtxTwo = ( m_aaVrtVecVol[sv] )[iv1];
    8361              : //                                                      Vertex * vrtxThree = ( m_aaVrtVecVol[sv] )[iv2];
    8362              : 
    8363              :                                                         // figure out which vertex is the base vertex
    8364              : 
    8365              :                                                         int indBasVrtx = -1;
    8366              : 
    8367              :                                                         // wie kann das nur stimmen, das Volumen hat doch mehr als 3 Vertizes....
    8368              :                                                         // zufällig für das Testbeispiel vielleicht richtig?
    8369              : //                                                      for( IndexType vrtxInd = 0; vrtxInd < triangVrtxNum; vrtxInd++ )
    8370            0 :                                                         for( IndexType vrtxInd = 0; vrtxInd < sv->num_vertices(); vrtxInd++ )
    8371              :                                                         {
    8372            0 :                                                                 if( sv->vertex(vrtxInd) == baseVrtx )
    8373            0 :                                                                         indBasVrtx = vrtxInd;
    8374              :                                                         }
    8375              :                                                         // muss der Loop nicht über die Vertizes des volumens gehen?????
    8376              : 
    8377              :                                                         // der Index des Basisvertex ist tabu für die Ausehnung der endenden fracture
    8378              : 
    8379            0 :                                                         bool belongsToEndingCleftFaces = (endingFractFacCutting == tFace);
    8380              : 
    8381              :                                                         bool belongstToEndingNotCuttingFacs = false;
    8382              : 
    8383            0 :                                                         for( Face * const & endingFractFacNotCutting : ecfsi.spuckVecEndingFractManifNotCutting() )
    8384              :                                                         {
    8385            0 :                                                                 if( tFace == endingFractFacNotCutting )
    8386              :                                                                 {
    8387              :                                                                         belongsToEndingCleftFaces = true;
    8388              :                                                                         belongstToEndingNotCuttingFacs = true;
    8389              :                                                                         UG_LOG("Want to create for not cutting ending fract face vol " << std::endl);
    8390              :                                                                 }
    8391            0 :                                                         }
    8392              : 
    8393            0 :                                                         if( belongsToEndingCleftFaces != faceIsEndingCleftCrossFace )
    8394              :                                                         {
    8395              :                                                                 UG_LOG("Widerspruch ending but not ending ECC" << std::endl);
    8396            0 :                                                                 UG_THROW("Widerspruch ending but not ending ECC" << std::endl);
    8397              : 
    8398              :                                                         }
    8399              : 
    8400            0 :                                                         if( belongsToEndingCleftFaces )
    8401              :                                                         {
    8402            0 :                                                                 if( ! faceIsEndingCleftCrossFace )
    8403              :                                                                 {
    8404              :                                                                         UG_LOG("Widerspruch ending but not ending ECC" << std::endl);
    8405              :                                                                 }
    8406              : 
    8407            0 :                                                                 if( iv0 == indBasVrtx )
    8408              :                                                                 {
    8409            0 :                                                                         if(    ( m_aaVrtVecVol[sv] )[iv0]
    8410            0 :                                                                                 && ( m_aaVrtVecVol[sv] )[iv1]
    8411            0 :                                                                                 && ( m_aaVrtVecVol[sv] )[iv2]
    8412              :                                                                         )
    8413              :                                                                         {
    8414              :                                                                                 //      create a new pyramid
    8415              : //                                                                              expVol = *m_grid.create<Pyramid>(
    8416              : //                                                                                                              PyramidDescriptor(sv->vertex(iv2), sv->vertex(iv1),
    8417              : //                                                                                                                                              (m_aaVrtVecVol[sv])[iv2],
    8418              : //                                                                                                                                              (m_aaVrtVecVol[sv])[iv1],
    8419              : //                                                                                                                                              (m_aaVrtVecVol[sv])[iv0]));
    8420              : 
    8421            0 :                                                                                 expVol = *m_grid.create<Pyramid>(
    8422            0 :                                                                                                                 PyramidDescriptor(sv->vertex(iv1), sv->vertex(iv2),
    8423              :                                                                                                                         (m_aaVrtVecVol[sv])[iv2],
    8424              :                                                                                                                         (m_aaVrtVecVol[sv])[iv1],
    8425              :                                                                                                                         (m_aaVrtVecVol[sv])[iv0]));
    8426              : 
    8427              :                                                                         }
    8428              :                                                                         else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8429            0 :                                                                                          && ( m_aaVrtVecVol[sv] )[iv1]
    8430              :                                                                         )
    8431              :                                                                         {
    8432              :                                                                                 //      create a new tetrahedron
    8433            0 :                                                                                 expVol = *m_grid.create<Tetrahedron>(
    8434            0 :                                                                                                                 TetrahedronDescriptor(sv->vertex(iv1),
    8435              :                                                                                                                         (m_aaVrtVecVol[sv])[iv1],
    8436            0 :                                                                                                                         (m_aaVrtVecVol[sv])[iv0],
    8437            0 :                                                                                                                         sv->vertex(iv2)));
    8438              :                                                                         }
    8439              : //                                                                      else if(    ( m_aaVrtVecVol[sv] )[iv1]
    8440              : //                                                                                       && ( m_aaVrtVecVol[sv] )[iv2]
    8441              : //                                                                      )
    8442              : //                                                                      {
    8443              : //                                                                              //      create a new Pyramid
    8444              : //                                                                              expVol = *m_grid.create<Pyramid>(
    8445              : //                                                                                                              PyramidDescriptor(sv->vertex(iv1), sv->vertex(iv2),
    8446              : //                                                                                                                      (m_aaVrtVecVol[sv])[iv2],
    8447              : //                                                                                                                      (m_aaVrtVecVol[sv])[iv1],
    8448              : //                                                                                                                      sv->vertex(iv0)));
    8449              : //                                                                      }
    8450              :                                                                         else if(    (m_aaVrtVecVol[sv])[iv0]
    8451            0 :                                                                                          && (m_aaVrtVecVol[sv])[iv2]
    8452              :                                                                         )
    8453              :                                                                         {
    8454              :                                                                                 //      create a new tetrahedron
    8455            0 :                                                                                 expVol = *m_grid.create<Tetrahedron>(
    8456            0 :                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2),
    8457              :                                                                                                                         (m_aaVrtVecVol[sv])[iv0],
    8458            0 :                                                                                                                         (m_aaVrtVecVol[sv])[iv2],
    8459            0 :                                                                                                                         sv->vertex(iv1)));
    8460              :                                                                         }
    8461              : //                                                                      else if( ( m_aaVrtVecVol[sv])[iv0] )
    8462              : //                                                                      {
    8463              : //                                                                              //      create a new Tetrahedron
    8464              : //                                                                              expVol = *m_grid.create<Tetrahedron>(
    8465              : //                                                                                                              TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8466              : //                                                                                                                                                       (m_aaVrtVecVol[sv])[iv0]));
    8467              : //                                                                      }
    8468              : //                                                                      else if( ( m_aaVrtVecVol[sv])[iv1] )
    8469              : //                                                                      {
    8470              : //                                                                              //      create a new Tetrahedron
    8471              : //                                                                              expVol = *m_grid.create<Tetrahedron>(
    8472              : //                                                                                                              TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8473              : //                                                                                                                                                       (m_aaVrtVecVol[sv])[iv1]));
    8474              : //                                                                      }
    8475              : //                                                                      else if( ( m_aaVrtVecVol[sv])[iv2] )
    8476              : //                                                                      {
    8477              : //                                                                              //      create a new Tetrahedron
    8478              : //                                                                              expVol = *m_grid.create<Tetrahedron>(
    8479              : //                                                                                                              TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8480              : //                                                                                                                                                       (m_aaVrtVecVol[sv])[iv2]));
    8481              : //                                                                      }
    8482              :                                                                         else
    8483              :                                                                         {
    8484              :                                                                                 //      Text from SR, still similar:
    8485              :                                                                                 //  this code-block should never be entered. If it is entered then
    8486              :                                                                                 //      we either selected the wrong faces (this shouldn't happen), or there
    8487              :                                                                                 //      are selected faces, which have fracture-boundary-vertices only.
    8488              :                                                                                 //      This is the same is if inner fracture edges exists, which are
    8489              :                                                                                 //      connected to two boundary vertices.
    8490              :                                                                                 //      Since we tried to remove those edges above, something went wrong.
    8491              :                                                                                 //      remove the temporary attachments and throw an error
    8492              : 
    8493              :                                                                                 UG_LOG("Tetraeder ECC Fehlt eine Loesung " << std::endl);
    8494            0 :                                                                                 detachMarkers();
    8495            0 :                                                                                 throw(UGError("Error in ExpandFractures3d Arte Stasi. Implementation Error."));
    8496              :                                                                                 return false;
    8497              :                                                                         }
    8498              : 
    8499              :                                                                 }
    8500            0 :                                                                 else if( iv1 == indBasVrtx )
    8501              :                                                                 {
    8502            0 :                                                                         if(    ( m_aaVrtVecVol[sv] )[iv0]
    8503            0 :                                                                                 && ( m_aaVrtVecVol[sv] )[iv1]
    8504            0 :                                                                                 && ( m_aaVrtVecVol[sv] )[iv2]
    8505              :                                                                         )
    8506              :                                                                         {
    8507              :                                                                                 //      create a new prism
    8508              : //                                                                              expVol = *m_grid.create<Pyramid>(
    8509              : //                                                                                                              PyramidDescriptor( sv->vertex(iv2), sv->vertex(iv0),
    8510              : //                                                                                                                                                              (m_aaVrtVecVol[sv])[iv2],
    8511              : //                                                                                                                                                              (m_aaVrtVecVol[sv])[iv1],
    8512              : //                                                                                                                                                              (m_aaVrtVecVol[sv])[iv0]));
    8513              : 
    8514              : 
    8515            0 :                                                                                 expVol = *m_grid.create<Pyramid>(
    8516            0 :                                                                                                                 PyramidDescriptor(sv->vertex(iv2), sv->vertex(iv0),
    8517              :                                                                                                                         (m_aaVrtVecVol[sv])[iv0],
    8518              :                                                                                                                         (m_aaVrtVecVol[sv])[iv2],
    8519              :                                                                                                                         (m_aaVrtVecVol[sv])[iv1]));
    8520              : 
    8521              :                                                                         }
    8522              :                                                                         else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8523            0 :                                                                                          && ( m_aaVrtVecVol[sv] )[iv1]
    8524              :                                                                         )
    8525              :                                                                         {
    8526              :                                                                                 //      create a new Pyramid
    8527            0 :                                                                                 expVol = *m_grid.create<Tetrahedron>(
    8528            0 :                                                                                                                 TetrahedronDescriptor(sv->vertex(iv0),
    8529              :                                                                                                                         (m_aaVrtVecVol[sv])[iv1],
    8530            0 :                                                                                                                         (m_aaVrtVecVol[sv])[iv0],
    8531            0 :                                                                                                                         sv->vertex(iv2)));
    8532              :                                                                         }
    8533              :                                                                         else if(    ( m_aaVrtVecVol[sv] )[iv1]
    8534            0 :                                                                                          && ( m_aaVrtVecVol[sv] )[iv2]
    8535              :                                                                         )
    8536              :                                                                         {
    8537              :                                                                                 //      create a new Pyramid
    8538            0 :                                                                                 expVol = *m_grid.create<Tetrahedron>(
    8539            0 :                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2),
    8540              :                                                                                                                         (m_aaVrtVecVol[sv])[iv2],
    8541            0 :                                                                                                                         (m_aaVrtVecVol[sv])[iv1],
    8542            0 :                                                                                                                         sv->vertex(iv0)));
    8543              :                                                                         }
    8544              : //                                                                      else if(    (m_aaVrtVecVol[sv])[iv0]
    8545              : //                                                                                       && (m_aaVrtVecVol[sv])[iv2]
    8546              : //                                                                      )
    8547              : //                                                                      {
    8548              : //                                                                              //      create a new Pyramid
    8549              : //                                                                              expVol = *m_grid.create<Pyramid>(
    8550              : //                                                                                                              PyramidDescriptor(sv->vertex(iv2), sv->vertex(iv0),
    8551              : //                                                                                                                      (m_aaVrtVecVol[sv])[iv0],
    8552              : //                                                                                                                      (m_aaVrtVecVol[sv])[iv2],
    8553              : //                                                                                                                      sv->vertex(iv1)));
    8554              : //                                                                      }
    8555              : //                                                                      else if( ( m_aaVrtVecVol[sv])[iv0] )
    8556              : //                                                                      {
    8557              : //                                                                              //      create a new Tetrahedron
    8558              : //                                                                              expVol = *m_grid.create<Tetrahedron>(
    8559              : //                                                                                                              TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8560              : //                                                                                                                                                       (m_aaVrtVecVol[sv])[iv0]));
    8561              : //                                                                      }
    8562              : //                                                                      else if( ( m_aaVrtVecVol[sv])[iv1] )
    8563              : //                                                                      {
    8564              : //                                                                              //      create a new Tetrahedron
    8565              : //                                                                              expVol = *m_grid.create<Tetrahedron>(
    8566              : //                                                                                                              TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8567              : //                                                                                                                                                       (m_aaVrtVecVol[sv])[iv1]));
    8568              : //                                                                      }
    8569              : //                                                                      else if( ( m_aaVrtVecVol[sv])[iv2] )
    8570              : //                                                                      {
    8571              : //                                                                              //      create a new Tetrahedron
    8572              : //                                                                              expVol = *m_grid.create<Tetrahedron>(
    8573              : //                                                                                                              TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8574              : //                                                                                                                                                       (m_aaVrtVecVol[sv])[iv2]));
    8575              : //                                                                      }
    8576              :                                                                         else
    8577              :                                                                         {
    8578              :                                                                                 //      Text from SR, still similar:
    8579              :                                                                                 //  this code-block should never be entered. If it is entered then
    8580              :                                                                                 //      we either selected the wrong faces (this shouldn't happen), or there
    8581              :                                                                                 //      are selected faces, which have fracture-boundary-vertices only.
    8582              :                                                                                 //      This is the same is if inner fracture edges exists, which are
    8583              :                                                                                 //      connected to two boundary vertices.
    8584              :                                                                                 //      Since we tried to remove those edges above, something went wrong.
    8585              :                                                                                 //      remove the temporary attachments and throw an error
    8586              : 
    8587              :                                                                                 UG_LOG("Tetraeder ECC Fehlt eine Loesung " << std::endl);
    8588            0 :                                                                                 detachMarkers();
    8589            0 :                                                                                 throw(UGError("Error in ExpandFractures3d Arte Stasi. Implementation Error."));
    8590              :                                                                                 return false;
    8591              :                                                                         }
    8592              :                                                                 }
    8593            0 :                                                                 else if( iv2 == indBasVrtx )
    8594              :                                                                 {
    8595            0 :                                                                         if(    ( m_aaVrtVecVol[sv] )[iv0]
    8596            0 :                                                                                 && ( m_aaVrtVecVol[sv] )[iv1]
    8597            0 :                                                                                 && ( m_aaVrtVecVol[sv] )[iv2]
    8598              :                                                                         )
    8599              :                                                                         {
    8600              :                                                                                 //      create a new prism
    8601              : //                                                                              expVol = *m_grid.create<Pyramid>(
    8602              : //                                                                                                              PyramidDescriptor(sv->vertex(iv1), sv->vertex(iv0),
    8603              : //                                                                                                                                              (m_aaVrtVecVol[sv])[iv2],
    8604              : //                                                                                                                                              (m_aaVrtVecVol[sv])[iv1],
    8605              : //                                                                                                                                              (m_aaVrtVecVol[sv])[iv0]));
    8606              : 
    8607            0 :                                                                                 expVol = *m_grid.create<Pyramid>(
    8608            0 :                                                                                                                 PyramidDescriptor(sv->vertex(iv0), sv->vertex(iv1),
    8609              :                                                                                                                         (m_aaVrtVecVol[sv])[iv1],
    8610              :                                                                                                                         (m_aaVrtVecVol[sv])[iv0],
    8611              :                                                                                                                         (m_aaVrtVecVol[sv])[iv2]));
    8612              : 
    8613              :                                                                         }
    8614              : //                                                                      else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8615              : //                                                                                       && ( m_aaVrtVecVol[sv] )[iv1]
    8616              : //                                                                      )
    8617              : //                                                                      {
    8618              : //                                                                              //      create a new Pyramid
    8619              : //                                                                              expVol = *m_grid.create<Pyramid>(
    8620              : //                                                                                                              PyramidDescriptor(sv->vertex(iv0), sv->vertex(iv1),
    8621              : //                                                                                                                      (m_aaVrtVecVol[sv])[iv1],
    8622              : //                                                                                                                      (m_aaVrtVecVol[sv])[iv0],
    8623              : //                                                                                                                      sv->vertex(iv2)));
    8624              : //                                                                      }
    8625              :                                                                         else if(    ( m_aaVrtVecVol[sv] )[iv1]
    8626            0 :                                                                                          && ( m_aaVrtVecVol[sv] )[iv2]
    8627              :                                                                         )
    8628              :                                                                         {
    8629              :                                                                                 //      create a new Pyramid
    8630            0 :                                                                                 expVol = *m_grid.create<Tetrahedron>(
    8631            0 :                                                                                                                 TetrahedronDescriptor(sv->vertex(iv1),
    8632              :                                                                                                                         (m_aaVrtVecVol[sv])[iv2],
    8633            0 :                                                                                                                         (m_aaVrtVecVol[sv])[iv1],
    8634            0 :                                                                                                                         sv->vertex(iv0)));
    8635              :                                                                         }
    8636              :                                                                         else if(    (m_aaVrtVecVol[sv])[iv0]
    8637            0 :                                                                                          && (m_aaVrtVecVol[sv])[iv2]
    8638              :                                                                         )
    8639              :                                                                         {
    8640              :                                                                                 //      create a new Pyramid
    8641            0 :                                                                                 expVol = *m_grid.create<Tetrahedron>(
    8642            0 :                                                                                                                 TetrahedronDescriptor(sv->vertex(iv0),
    8643              :                                                                                                                         (m_aaVrtVecVol[sv])[iv0],
    8644            0 :                                                                                                                         (m_aaVrtVecVol[sv])[iv2],
    8645            0 :                                                                                                                         sv->vertex(iv1)));
    8646              :                                                                         }
    8647              : //                                                                      else if( ( m_aaVrtVecVol[sv])[iv0] )
    8648              : //                                                                      {
    8649              : //                                                                              //      create a new Tetrahedron
    8650              : //                                                                              expVol = *m_grid.create<Tetrahedron>(
    8651              : //                                                                                                              TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8652              : //                                                                                                                                                       (m_aaVrtVecVol[sv])[iv0]));
    8653              : //                                                                      }
    8654              : //                                                                      else if( ( m_aaVrtVecVol[sv])[iv1] )
    8655              : //                                                                      {
    8656              : //                                                                              //      create a new Tetrahedron
    8657              : //                                                                              expVol = *m_grid.create<Tetrahedron>(
    8658              : //                                                                                                              TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8659              : //                                                                                                                                                       (m_aaVrtVecVol[sv])[iv1]));
    8660              : //                                                                      }
    8661              : //                                                                      else if( ( m_aaVrtVecVol[sv])[iv2] )
    8662              : //                                                                      {
    8663              : //                                                                              //      create a new Tetrahedron
    8664              : //                                                                              expVol = *m_grid.create<Tetrahedron>(
    8665              : //                                                                                                              TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8666              : //                                                                                                                                                       (m_aaVrtVecVol[sv])[iv2]));
    8667              : //                                                                      }
    8668              :                                                                         else
    8669              :                                                                         {
    8670              :                                                                                 //      Text from SR, still similar:
    8671              :                                                                                 //  this code-block should never be entered. If it is entered then
    8672              :                                                                                 //      we either selected the wrong faces (this shouldn't happen), or there
    8673              :                                                                                 //      are selected faces, which have fracture-boundary-vertices only.
    8674              :                                                                                 //      This is the same is if inner fracture edges exists, which are
    8675              :                                                                                 //      connected to two boundary vertices.
    8676              :                                                                                 //      Since we tried to remove those edges above, something went wrong.
    8677              :                                                                                 //      remove the temporary attachments and throw an error
    8678              : 
    8679              :                                                                                 UG_LOG("Tetraeder ECC Fehlt eine Loesung " << std::endl);
    8680            0 :                                                                                 detachMarkers();
    8681            0 :                                                                                 throw(UGError("Error in ExpandFractures3d Arte Stasi. Implementation Error."));
    8682              :                                                                                 return false;
    8683              :                                                                         }
    8684              : 
    8685              :                                                                 }
    8686              : 
    8687            0 :                                                                 if( belongstToEndingNotCuttingFacs )
    8688              :                                                                 {
    8689            0 :                                                                         if( expVol )
    8690              :                                                                         {
    8691            0 :                                                                                 UG_LOG("not cutting vol created at " << CalculateCenter(expVol, m_aaPos ) << std::endl );
    8692              : //                                                                              m_sh.assign_subset(expVol, m_sh.num_subsets());
    8693              :                                                                         }
    8694              :                                                                         else
    8695              :                                                                         {
    8696              :                                                                                 UG_LOG("was not able to create vol for not cutting " << std::endl);
    8697              :                                                                         }
    8698              :                                                                 }
    8699              :                                                         }
    8700              :                                                         else
    8701              :                                                         {
    8702              :                                                                 // test if face belongs to the closed faces
    8703              : 
    8704              :                                                                 std::pair<Face*,Face*> const & closedNeighbrs = ecfsi.spuckPairNeighbouredFractClosedManifEl();
    8705              : 
    8706              : 
    8707            0 :                                                                 if( closedNeighbrs.first == tFace || closedNeighbrs.second == tFace )
    8708              :                                                                 {
    8709              : 
    8710              :                                                                         // figure out the vertex that is not from the cut edge
    8711              : 
    8712              :                                                                         Vertex * freeVrtx = nullptr;
    8713              : 
    8714              :                                                                         // wasn das für ein Käse.....
    8715            0 :                                                                         for( IndexType vrtxInd = 0; vrtxInd < triangVrtxNum; vrtxInd++ )
    8716              : //                                                                      for( IndexType vrtxInd = 0; vrtxInd < sv->num_vertices(); vrtxInd++ )
    8717              :                                                                         {
    8718            0 :                                                                                 if( ! EdgeContains(cutEdge, tFace->vertex(vrtxInd)))
    8719            0 :                                                                                         freeVrtx = tFace->vertex(vrtxInd);
    8720              :                                                                         }
    8721              : 
    8722            0 :                                                                         if( freeVrtx == nullptr )
    8723              :                                                                         {
    8724              :                                                                                 UG_LOG("Immer noch null " << std::endl);
    8725            0 :                                                                                 UG_THROW("Immer noch null " << std::endl);
    8726              :                                                                         }
    8727              : 
    8728              : //                                                                      int freeVrtxInd = -1;
    8729              : //                                                                      int secondCutEdgVrtxInd = -1;
    8730              : //
    8731              : //                                                                      for( IndexType vrtxInd = 0; vrtxInd < sv->num_vertices(); vrtxInd++ )
    8732              : //                                                                      {
    8733              : //                                                                              if( ! EdgeContains(cutEdge, freeVrtx))
    8734              : //                                                                                      freeVrtxInd = vrtxInd;
    8735              : //
    8736              : //                                                                              if( secondVrtxCutEdge == secondVrtxCutEdge)
    8737              : //                                                                                      secondCutEdgVrtxInd = vrtxInd;
    8738              : //                                                                      }
    8739              : 
    8740              : 
    8741              :                                                                         // for the "pyramid", exclude the base Vertex
    8742              :                                                                         // for the other tetrahedron, exclude the shifted of the non-base of the cut edge
    8743              :                                                                         // i.e. of secondVrtxCutEdge
    8744              : 
    8745              : //                                                                      Vertex * vrtxNotFromCutEdge = tFace->vertex(freeVrtxInd);
    8746              : 
    8747              :                                                                         // relate iv0, iv1, iv2 to vrtxNotFromCutEdge, base
    8748              : 
    8749            0 :                                                                         if( iv0 == indBasVrtx )
    8750              :                                                                         {
    8751              : 
    8752            0 :                                                                                 if(    ( m_aaVrtVecVol[sv] )[iv0]
    8753            0 :                                                                                         && ( m_aaVrtVecVol[sv] )[iv1]
    8754            0 :                                                                                         && ( m_aaVrtVecVol[sv] )[iv2]
    8755              :                                                                                 )
    8756              :                                                                                 {
    8757            0 :                                                                                         expVol = *m_grid.create<Pyramid>(
    8758            0 :                                                                                                                         PyramidDescriptor(sv->vertex(iv1), sv->vertex(iv2),
    8759              :                                                                                                                                 (m_aaVrtVecVol[sv])[iv2],
    8760              :                                                                                                                                 (m_aaVrtVecVol[sv])[iv1],
    8761              :                                                                                                                                 ( m_aaVrtVecVol[sv] )[iv0]));
    8762              : 
    8763            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8764            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8765            0 :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv0]));
    8766              : 
    8767              :                                                                                 }
    8768              :                                                                                 else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8769            0 :                                                                                                  && ( m_aaVrtVecVol[sv] )[iv1]
    8770              :                                                                                 )
    8771              :                                                                                 {
    8772            0 :                                                                                         expVol = *m_grid.create<Tetrahedron>(
    8773            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), ( m_aaVrtVecVol[sv] )[iv0],
    8774              :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv1]));
    8775              : 
    8776              : 
    8777            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8778            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8779            0 :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv0]));
    8780              :                                                                                 }
    8781              : //                                                                              else if(    ( m_aaVrtVecVol[sv] )[iv1]
    8782              : //                                                                                      && ( m_aaVrtVecVol[sv] )[iv2]
    8783              : //                                                                              )
    8784              : //                                                                              {
    8785              : //
    8786              : //                                                                              }
    8787              :                                                                                 else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8788            0 :                                                                                         && ( m_aaVrtVecVol[sv] )[iv2]
    8789              :                                                                                 )
    8790              :                                                                                 {
    8791              : 
    8792            0 :                                                                                         expVol = *m_grid.create<Tetrahedron>(
    8793            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1),  ( m_aaVrtVecVol[sv] )[iv0],
    8794              :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv2]));
    8795              : 
    8796            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8797            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8798            0 :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv0]));
    8799              :                                                                                 } //
    8800            0 :                                                                                 else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8801              :                                                                                 )
    8802              :                                                                                 {
    8803              : 
    8804            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8805            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8806              :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv0]));
    8807              :                                                                                 } //
    8808              : 
    8809              : 
    8810              : 
    8811              :                                                                         }
    8812              : 
    8813            0 :                                                                         if( iv1 == indBasVrtx )
    8814              :                                                                         {
    8815              : 
    8816            0 :                                                                                 if(    ( m_aaVrtVecVol[sv] )[iv0]
    8817            0 :                                                                                         && ( m_aaVrtVecVol[sv] )[iv1]
    8818            0 :                                                                                         && ( m_aaVrtVecVol[sv] )[iv2]
    8819              :                                                                                 )
    8820              :                                                                                 {
    8821            0 :                                                                                         expVol = *m_grid.create<Pyramid>(
    8822            0 :                                                                                                                         PyramidDescriptor(sv->vertex(iv2), sv->vertex(iv0),
    8823              :                                                                                                                                 (m_aaVrtVecVol[sv])[iv0],
    8824              :                                                                                                                                 (m_aaVrtVecVol[sv])[iv2],
    8825              :                                                                                                                                 ( m_aaVrtVecVol[sv] )[iv1]));
    8826              : 
    8827            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8828            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8829            0 :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv1]));
    8830              : 
    8831              :                                                                                 }
    8832              :                                                                                 else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8833            0 :                                                                                         && ( m_aaVrtVecVol[sv] )[iv1]
    8834              :                                                                                 )
    8835              :                                                                                 {
    8836            0 :                                                                                         expVol = *m_grid.create<Tetrahedron>(
    8837            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), ( m_aaVrtVecVol[sv] )[iv1], sv->vertex(iv0),
    8838              :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv0]));
    8839              : 
    8840              : 
    8841            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8842            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8843            0 :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv1]));
    8844              : 
    8845              :                                                                                 }
    8846              :                                                                                 else if(    ( m_aaVrtVecVol[sv] )[iv1]
    8847            0 :                                                                                         && ( m_aaVrtVecVol[sv] )[iv2]
    8848              :                                                                                 )
    8849              :                                                                                 {
    8850            0 :                                                                                         expVol = *m_grid.create<Tetrahedron>(
    8851            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), ( m_aaVrtVecVol[sv] )[iv1], sv->vertex(iv0),
    8852              :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv2]));
    8853              : 
    8854            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8855            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8856            0 :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv1]));
    8857              : 
    8858              :                                                                                 }
    8859              : //                                                                              else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8860              : //                                                                                      && ( m_aaVrtVecVol[sv] )[iv2]
    8861              : //                                                                              )
    8862              : //                                                                              {
    8863              : //
    8864              : //                                                                              }
    8865            0 :                                                                                 else if(    ( m_aaVrtVecVol[sv] )[iv1]
    8866              :                                                                                 )
    8867              :                                                                                 {
    8868              : 
    8869            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8870            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8871              :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv1]));
    8872              : 
    8873              :                                                                                 }
    8874              : 
    8875              : 
    8876              :                                                                         }
    8877              : 
    8878            0 :                                                                         if( iv2 == indBasVrtx )
    8879              :                                                                         {
    8880              : 
    8881            0 :                                                                                 if(    ( m_aaVrtVecVol[sv] )[iv0]
    8882            0 :                                                                                         && ( m_aaVrtVecVol[sv] )[iv1]
    8883            0 :                                                                                         && ( m_aaVrtVecVol[sv] )[iv2]
    8884              :                                                                                 )
    8885              :                                                                                 {
    8886              : 
    8887            0 :                                                                                         expVol = *m_grid.create<Pyramid>(
    8888            0 :                                                                                                                         PyramidDescriptor(sv->vertex(iv0), sv->vertex(iv1),
    8889              :                                                                                                                                 (m_aaVrtVecVol[sv])[iv1],
    8890              :                                                                                                                                 (m_aaVrtVecVol[sv])[iv0],
    8891              :                                                                                                                                 ( m_aaVrtVecVol[sv] )[iv2]));
    8892              : 
    8893            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8894            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8895            0 :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv2]));
    8896              :                                                                                 }
    8897              : 
    8898              :         //                                                                      else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8899              :         //                                                                              && ( m_aaVrtVecVol[sv] )[iv1]
    8900              :         //                                                                      )
    8901              :         //                                                                      {
    8902              :         //
    8903              :         //                                                                      }
    8904              :                                                                                 else if(    ( m_aaVrtVecVol[sv] )[iv1]
    8905            0 :                                                                                         && ( m_aaVrtVecVol[sv] )[iv2]
    8906              :                                                                                 )
    8907              :                                                                                 {
    8908              : 
    8909            0 :                                                                                         expVol = *m_grid.create<Tetrahedron>(
    8910            0 :                                                                                                                         TetrahedronDescriptor(( m_aaVrtVecVol[sv] )[iv2], sv->vertex(iv1), sv->vertex(iv0),
    8911              :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv1]));
    8912              : 
    8913            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8914            0 :                                                                                                                         TetrahedronDescriptor( sv->vertex(iv1) , sv->vertex(iv1), sv->vertex(iv0),
    8915            0 :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv2]));
    8916              : 
    8917              :                                                                                 }
    8918              :                                                                                 else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8919            0 :                                                                                         && ( m_aaVrtVecVol[sv] )[iv2]
    8920              :                                                                                 )
    8921              :                                                                                 {
    8922            0 :                                                                                         expVol = *m_grid.create<Tetrahedron>(
    8923            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), ( m_aaVrtVecVol[sv] )[iv0],
    8924              :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv2]));
    8925              : 
    8926            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8927            0 :                                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8928            0 :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv2]));
    8929              :                                                                                 } //
    8930            0 :                                                                                 else if( ( m_aaVrtVecVol[sv] )[iv2]
    8931            0 :                                                                                 )
    8932              :                                                                                 {
    8933            0 :                                                                                         expVolTwo = *m_grid.create<Tetrahedron>(
    8934            0 :                                                                                                                         TetrahedronDescriptor( sv->vertex(iv1) , sv->vertex(iv1), sv->vertex(iv0),
    8935              :                                                                                                                                                                  (m_aaVrtVecVol[sv])[iv2]));
    8936              :                                                                                 }
    8937              : 
    8938              : 
    8939              : 
    8940              :                                                                         }
    8941              : 
    8942              :                                                                 }
    8943              : 
    8944              : 
    8945              :                                                                 std::vector<Face*> const & closedNotNeighbr = ecfsi.spuckVecClosedFracManifElNoNeighbr();
    8946              : 
    8947            0 :                                                                 for( Face * fac : closedNotNeighbr )
    8948              :                                                                 {
    8949            0 :                                                                         if( fac == tFace )
    8950              :                                                                         {
    8951            0 :                                                                                 if( iv0 == indBasVrtx )
    8952              :                                                                                 {
    8953              : 
    8954            0 :                                                                                         if(    ( m_aaVrtVecVol[sv] )[iv0]
    8955            0 :                                                                                                 && ( m_aaVrtVecVol[sv] )[iv1]
    8956            0 :                                                                                                 && ( m_aaVrtVecVol[sv] )[iv2]
    8957              :                                                                                         )
    8958              :                                                                                         {
    8959              : 
    8960            0 :                                                                                                 expVol = *m_grid.create<Tetrahedron>(
    8961            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8962              :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv0]));
    8963              : 
    8964            0 :                                                                                                 expVolTwo = *m_grid.create<Pyramid>(
    8965            0 :                                                                                                                                 PyramidDescriptor(sv->vertex(iv1), sv->vertex(iv2),
    8966              :                                                                                                                                         (m_aaVrtVecVol[sv])[iv2],
    8967              :                                                                                                                                         (m_aaVrtVecVol[sv])[iv1],
    8968            0 :                                                                                                                                         ( m_aaVrtVecVol[sv] )[iv0]));
    8969              : 
    8970              :                                                                                         }
    8971              :                                                                                         else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8972            0 :                                                                                                 && ( m_aaVrtVecVol[sv] )[iv1]
    8973              :                                                                                         )
    8974              :                                                                                         {
    8975            0 :                                                                                                 expVol = *m_grid.create<Tetrahedron>(
    8976            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    8977              :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv0]));
    8978              : 
    8979            0 :                                                                                                 expVolTwo = *m_grid.create<Tetrahedron>(
    8980            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), ( m_aaVrtVecVol[sv] )[iv0],
    8981            0 :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv1]));
    8982              : 
    8983              :                                                                                         }
    8984              : //                                                                                      else if(    ( m_aaVrtVecVol[sv] )[iv1]
    8985              : //                                                                                              && ( m_aaVrtVecVol[sv] )[iv2]
    8986              : //                                                                                      )
    8987              : //                                                                                      {
    8988              : //
    8989              : //                                                                                      }
    8990              : //                                                                                              && ( m_aaVrtVecVol[sv] )[iv2]
    8991              : //                                                                                      )
    8992              : //                                                                                      {
    8993              : //
    8994              : //                                                                                      }
    8995            0 :                                                                                         else if(    ( m_aaVrtVecVol[sv] )[iv0]
    8996              :                                                                                         )
    8997              :                                                                                         {
    8998            0 :                                                                                                 expVol = *m_grid.create<Tetrahedron>(
    8999            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9000              :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv0]));
    9001              : 
    9002              : 
    9003              :                                                                                         }
    9004              : 
    9005              : 
    9006              : 
    9007              : 
    9008              :                                                                                 }
    9009              : 
    9010            0 :                                                                                 if( iv1 == indBasVrtx )
    9011              :                                                                                 {
    9012              : 
    9013            0 :                                                                                         if(    ( m_aaVrtVecVol[sv] )[iv0]
    9014            0 :                                                                                                 && ( m_aaVrtVecVol[sv] )[iv1]
    9015            0 :                                                                                                 && ( m_aaVrtVecVol[sv] )[iv2]
    9016              :                                                                                         )
    9017              :                                                                                         {
    9018            0 :                                                                                                 expVol = *m_grid.create<Tetrahedron>(
    9019            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9020              :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv1]));
    9021              : 
    9022            0 :                                                                                                 expVolTwo = *m_grid.create<Pyramid>(
    9023            0 :                                                                                                                                 PyramidDescriptor(sv->vertex(iv2), sv->vertex(iv0),
    9024              :                                                                                                                                         (m_aaVrtVecVol[sv])[iv0],
    9025              :                                                                                                                                         (m_aaVrtVecVol[sv])[iv2],
    9026            0 :                                                                                                                                         ( m_aaVrtVecVol[sv] )[iv1]));
    9027              : 
    9028              :                                                                                         }
    9029              :                                                                                         else if(    ( m_aaVrtVecVol[sv] )[iv0]
    9030            0 :                                                                                                 && ( m_aaVrtVecVol[sv] )[iv1]
    9031              :                                                                                         )
    9032              :                                                                                         {
    9033            0 :                                                                                                 expVol = *m_grid.create<Tetrahedron>(
    9034            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9035              :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv1]));
    9036              : 
    9037            0 :                                                                                                 expVolTwo = *m_grid.create<Tetrahedron>(
    9038            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), ( m_aaVrtVecVol[sv] )[iv1], sv->vertex(iv0),
    9039            0 :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv0]));
    9040              : 
    9041              :                                                                                         }
    9042              :                                                                                         else if(    ( m_aaVrtVecVol[sv] )[iv1]
    9043            0 :                                                                                                 && ( m_aaVrtVecVol[sv] )[iv2]
    9044              :                                                                                         )
    9045              :                                                                                         {
    9046            0 :                                                                                                 expVol = *m_grid.create<Tetrahedron>(
    9047            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9048              :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv1]));
    9049              : 
    9050            0 :                                                                                                 expVolTwo = *m_grid.create<Tetrahedron>(
    9051            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), ( m_aaVrtVecVol[sv] )[iv1], sv->vertex(iv0),
    9052            0 :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv2]));
    9053              : 
    9054              :                                                                                         }
    9055              : //                                                                                      else if(    ( m_aaVrtVecVol[sv] )[iv0]
    9056              : //                                                                                              && ( m_aaVrtVecVol[sv] )[iv2]
    9057              : //                                                                                      )
    9058              : //                                                                                      {
    9059              : //
    9060              : //                                                                                      }
    9061            0 :                                                                                         else if(    ( m_aaVrtVecVol[sv] )[iv1]
    9062              :                                                                                         )
    9063              :                                                                                         {
    9064            0 :                                                                                                 expVol = *m_grid.create<Tetrahedron>(
    9065            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9066              :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv1]));
    9067              : 
    9068              :                                                                                         }
    9069              : 
    9070              : 
    9071              :                                                                                 }
    9072              : 
    9073            0 :                                                                                 if( iv2 == indBasVrtx )
    9074              :                                                                                 {
    9075            0 :                                                                                         if(    ( m_aaVrtVecVol[sv] )[iv0]
    9076            0 :                                                                                                 && ( m_aaVrtVecVol[sv] )[iv1]
    9077            0 :                                                                                                 && ( m_aaVrtVecVol[sv] )[iv2]
    9078              :                                                                                         )
    9079              :                                                                                         {
    9080              : 
    9081            0 :                                                                                                 expVol = *m_grid.create<Tetrahedron>(
    9082            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9083              :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv2]));
    9084              : 
    9085            0 :                                                                                                 expVolTwo = *m_grid.create<Pyramid>(
    9086            0 :                                                                                                                                 PyramidDescriptor(sv->vertex(iv0), sv->vertex(iv1),
    9087              :                                                                                                                                         (m_aaVrtVecVol[sv])[iv1],
    9088              :                                                                                                                                         (m_aaVrtVecVol[sv])[iv0],
    9089            0 :                                                                                                                                         ( m_aaVrtVecVol[sv] )[iv2]));
    9090              : 
    9091              :                                                                                         }
    9092              :         //                                                                              else if(    ( m_aaVrtVecVol[sv] )[iv0]
    9093              :         //                                                                                      && ( m_aaVrtVecVol[sv] )[iv1]
    9094              :         //                                                                              )
    9095              :         //                                                                              {
    9096              :         //
    9097              :         //                                                                              }
    9098              :                                                                                         else if(    ( m_aaVrtVecVol[sv] )[iv1]
    9099            0 :                                                                                                 && ( m_aaVrtVecVol[sv] )[iv2]
    9100              :                                                                                         )
    9101              :                                                                                         {
    9102            0 :                                                                                                 expVol = *m_grid.create<Tetrahedron>(
    9103            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9104              :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv2]));
    9105              : 
    9106            0 :                                                                                                 expVolTwo = *m_grid.create<Tetrahedron>(
    9107            0 :                                                                                                                                 TetrahedronDescriptor( ( m_aaVrtVecVol[sv] )[iv2], sv->vertex(iv1), sv->vertex(iv0),
    9108            0 :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv1]));
    9109              : 
    9110              :                                                                                         }
    9111              :                                                                                         else if(    ( m_aaVrtVecVol[sv] )[iv0]
    9112            0 :                                                                                                 && ( m_aaVrtVecVol[sv] )[iv2]
    9113              :                                                                                         )
    9114              :                                                                                         {
    9115            0 :                                                                                                 expVol = *m_grid.create<Tetrahedron>(
    9116            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9117              :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv2]));
    9118              : 
    9119            0 :                                                                                                 expVolTwo = *m_grid.create<Tetrahedron>(
    9120            0 :                                                                                                                                 TetrahedronDescriptor( ( m_aaVrtVecVol[sv] )[iv2], sv->vertex(iv1), sv->vertex(iv0),
    9121            0 :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv0]));
    9122              : 
    9123              :                                                                                         }       //
    9124            0 :                                                                                         else if(   ( m_aaVrtVecVol[sv] )[iv2]
    9125            0 :                                                                                         )
    9126              :                                                                                         {
    9127            0 :                                                                                                 expVol = *m_grid.create<Tetrahedron>(
    9128            0 :                                                                                                                                 TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9129              :                                                                                                                                                                          (m_aaVrtVecVol[sv])[iv2]));
    9130              : 
    9131              : 
    9132              :                                                                                         }
    9133              : 
    9134              :                                                                                 }
    9135              : 
    9136              :                                                                         }
    9137              :                                                                 }
    9138              : 
    9139              : #if 0
    9140              : 
    9141              :                                                                 if(    ( m_aaVrtVecVol[sv] )[iv0]
    9142              :                                                                         && ( m_aaVrtVecVol[sv] )[iv1]
    9143              :                                                                         && ( m_aaVrtVecVol[sv] )[iv2]
    9144              :                                                                 )
    9145              :                                                                 {
    9146              :                                                                         //      create a new prism
    9147              :                                                                         expVol = *m_grid.create<Prism>(
    9148              :                                                                                                         PrismDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9149              :                                                                                                                                         (m_aaVrtVecVol[sv])[iv2],
    9150              :                                                                                                                                         (m_aaVrtVecVol[sv])[iv1],
    9151              :                                                                                                                                         (m_aaVrtVecVol[sv])[iv0]));
    9152              :                                                                 }
    9153              :                                                                 else if(    ( m_aaVrtVecVol[sv] )[iv0]
    9154              :                                                                                  && ( m_aaVrtVecVol[sv] )[iv1]
    9155              :                                                                 )
    9156              :                                                                 {
    9157              :                                                                         //      create a new Pyramid
    9158              :                                                                         expVol = *m_grid.create<Pyramid>(
    9159              :                                                                                                         PyramidDescriptor(sv->vertex(iv0), sv->vertex(iv1),
    9160              :                                                                                                                 (m_aaVrtVecVol[sv])[iv1],
    9161              :                                                                                                                 (m_aaVrtVecVol[sv])[iv0],
    9162              :                                                                                                                 sv->vertex(iv2)));
    9163              :                                                                 }
    9164              :                                                                 else if(    ( m_aaVrtVecVol[sv] )[iv1]
    9165              :                                                                                  && ( m_aaVrtVecVol[sv] )[iv2]
    9166              :                                                                 )
    9167              :                                                                 {
    9168              :                                                                         //      create a new Pyramid
    9169              :                                                                         expVol = *m_grid.create<Pyramid>(
    9170              :                                                                                                         PyramidDescriptor(sv->vertex(iv1), sv->vertex(iv2),
    9171              :                                                                                                                 (m_aaVrtVecVol[sv])[iv2],
    9172              :                                                                                                                 (m_aaVrtVecVol[sv])[iv1],
    9173              :                                                                                                                 sv->vertex(iv0)));
    9174              :                                                                 }
    9175              :                                                                 else if(    (m_aaVrtVecVol[sv])[iv0]
    9176              :                                                                                  && (m_aaVrtVecVol[sv])[iv2]
    9177              :                                                                 )
    9178              :                                                                 {
    9179              :                                                                         //      create a new Pyramid
    9180              :                                                                         expVol = *m_grid.create<Pyramid>(
    9181              :                                                                                                         PyramidDescriptor(sv->vertex(iv2), sv->vertex(iv0),
    9182              :                                                                                                                 (m_aaVrtVecVol[sv])[iv0],
    9183              :                                                                                                                 (m_aaVrtVecVol[sv])[iv2],
    9184              :                                                                                                                 sv->vertex(iv1)));
    9185              :                                                                 }
    9186              :                                                                 else if( ( m_aaVrtVecVol[sv])[iv0] )
    9187              :                                                                 {
    9188              :                                                                         //      create a new Tetrahedron
    9189              :                                                                         expVol = *m_grid.create<Tetrahedron>(
    9190              :                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9191              :                                                                                                                                                  (m_aaVrtVecVol[sv])[iv0]));
    9192              :                                                                 }
    9193              :                                                                 else if( ( m_aaVrtVecVol[sv])[iv1] )
    9194              :                                                                 {
    9195              :                                                                         //      create a new Tetrahedron
    9196              :                                                                         expVol = *m_grid.create<Tetrahedron>(
    9197              :                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9198              :                                                                                                                                                  (m_aaVrtVecVol[sv])[iv1]));
    9199              :                                                                 }
    9200              :                                                                 else if( ( m_aaVrtVecVol[sv])[iv2] )
    9201              :                                                                 {
    9202              :                                                                         //      create a new Tetrahedron
    9203              :                                                                         expVol = *m_grid.create<Tetrahedron>(
    9204              :                                                                                                         TetrahedronDescriptor(sv->vertex(iv2), sv->vertex(iv1), sv->vertex(iv0),
    9205              :                                                                                                                                                  (m_aaVrtVecVol[sv])[iv2]));
    9206              :                                                                 }
    9207              :                                                                 else
    9208              :                                                                 {
    9209              :                                                                         //      Text from SR, still similar:
    9210              :                                                                         //  this code-block should never be entered. If it is entered then
    9211              :                                                                         //      we either selected the wrong faces (this shouldn't happen), or there
    9212              :                                                                         //      are selected faces, which have fracture-boundary-vertices only.
    9213              :                                                                         //      This is the same is if inner fracture edges exists, which are
    9214              :                                                                         //      connected to two boundary vertices.
    9215              :                                                                         //      Since we tried to remove those edges above, something went wrong.
    9216              :                                                                         //      remove the temporary attachments and throw an error
    9217              : 
    9218              :                                                                         UG_LOG("Tetraeder Fehlt eine Loesung " << std::endl);
    9219              :                                                                         detachMarkers();
    9220              :                                                                         throw(UGError("Error in ExpandFractures3d Arte Stasi. Implementation Error."));
    9221              :                                                                         return false;
    9222              :                                                                 }
    9223              : 
    9224              : 
    9225              : #endif
    9226              : 
    9227            0 :                                                         }
    9228              : 
    9229              : 
    9230              :                                                 }
    9231              :                                                 else
    9232              :                                                 {
    9233              :                                                         //      traditionally only tetrahedrons are supported. This section thus raises an error
    9234              :                                                         // Markus tries to implement also Hexahedra
    9235              :                 //                                                                      grid.detach_from_vertices(aVrtVec);
    9236              :                 //                                                              grid.detach_from_volumes(aVrtVec);
    9237              :                 //                                                      grid.detach_from_vertices(aAdjMarker);
    9238              :                 //                                                      grid.detach_from_edges(aAdjMarker);
    9239            0 :                                                         detachMarkers();
    9240            0 :                                                         throw(UGError("Incomplete implementation error in ExpandFractures3d Arte ending crossing clefts."));
    9241              :                                                         return false;
    9242              :                                                 }
    9243              : 
    9244            0 :                                                 if(expVol)
    9245              :                                                 {
    9246              : 
    9247            0 :                                                         IndexType newSubs = m_fracInfosBySubset.at(m_sh.get_subset_index(tFace)).newSubsetIndex;
    9248              : 
    9249            0 :                                                         subsOfNewVolumes.push_back( newSubs );
    9250              : 
    9251            0 :                                                         m_sh.assign_subset(expVol, newSubs);
    9252              : 
    9253            0 :                                                         newFractureVolumes.push_back(expVol);
    9254              :                                                 }
    9255              : 
    9256            0 :                                                 if(expVolTwo)
    9257              :                                                 {
    9258              : 
    9259            0 :                                                         IndexType newSubs = m_fracInfosBySubset.at(m_sh.get_subset_index(tFace)).newSubsetIndex;
    9260              : 
    9261            0 :                                                         subsOfNewVolumes.push_back( newSubs );
    9262              : 
    9263            0 :                                                         m_sh.assign_subset(expVolTwo, newSubs);
    9264              : 
    9265            0 :                                                         newFractureVolumes.push_back(expVolTwo);
    9266              :                                                 }
    9267              : 
    9268              :                                         }
    9269              :                                 }
    9270            0 :                         }
    9271            0 :                 }
    9272              :         }
    9273              : 
    9274              : 
    9275              :         return true;
    9276              : }
    9277              : 
    9278            0 : bool ArteExpandFracs3D::createTheDiamonds()
    9279              : {
    9280            0 :         diamonds::DiamondsEstablish3D establishDiams( m_grid, m_sh, m_vecVolManifVrtxCombiToShrink4Diams );
    9281              : 
    9282              :         UG_LOG("Establishing diamonds" << std::endl);
    9283              : 
    9284            0 :         return establishDiams.createTheDiamonds(m_diamondsOnlyPreform);
    9285              : 
    9286              : //      IndexType sudos = m_sh.num_subsets();
    9287              : //
    9288              : //      for( auto & vmvcd : m_vecVolManifVrtxCombiToShrink4Diams )
    9289              : //      {
    9290              : //              Volume* vol;
    9291              : //              vmvcd.spuckVol(vol);
    9292              : //
    9293              : //              m_sh.assign_subset(vol, sudos);
    9294              : //      }
    9295              : //
    9296              : //      UG_LOG("Established diamonds" << std::endl);
    9297              : //
    9298              : //
    9299              : //      return true;
    9300            0 : }
    9301              : 
    9302              : } /* namespace arte */
    9303              : 
    9304              : } /* namespace ug */
        

Generated by: LCOV version 2.0-1