LCOV - code coverage report
Current view: top level - ugbase/lib_grid/file_io - file_io.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 327 0
Test Date: 2026-09-22 09:15:05 Functions: 0.0 % 62 0

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2009-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Sebastian Reiter
       4              :  * 
       5              :  * This file is part of UG4.
       6              :  * 
       7              :  * UG4 is free software: you can redistribute it and/or modify it under the
       8              :  * terms of the GNU Lesser General Public License version 3 (as published by the
       9              :  * Free Software Foundation) with the following additional attribution
      10              :  * requirements (according to LGPL/GPL v3 §7):
      11              :  * 
      12              :  * (1) The following notice must be displayed in the Appropriate Legal Notices
      13              :  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
      14              :  * 
      15              :  * (2) The following notice must be displayed at a prominent place in the
      16              :  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
      17              :  * 
      18              :  * (3) The following bibliography is recommended for citation and must be
      19              :  * preserved in all covered files:
      20              :  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
      21              :  *   parallel geometric multigrid solver on hierarchically distributed grids.
      22              :  *   Computing and visualization in science 16, 4 (2013), 151-164"
      23              :  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
      24              :  *   flexible software system for simulating pde based models on high performance
      25              :  *   computers. Computing and visualization in science 16, 4 (2013), 165-179"
      26              :  * 
      27              :  * This program is distributed in the hope that it will be useful,
      28              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      29              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      30              :  * GNU Lesser General Public License for more details.
      31              :  */
      32              : 
      33              : #include <string>
      34              : #include "file_io.h"
      35              : #include "lib_grid/algorithms/attachment_util.h"
      36              : #include "common/util/path_provider.h"
      37              : #include "common/util/file_util.h"
      38              : #include "common/util/string_util.h"
      39              : #include "lib_grid/parallelization/distributed_grid.h"
      40              : #include "lib_grid/algorithms/subset_util.h"
      41              : #include "lib_grid/tools/surface_view.h"
      42              : 
      43              : #include "file_io_2df.h"
      44              : #include "file_io_art.h"
      45              : #include "file_io_asc.h"
      46              : #include "file_io_txt.h"
      47              : #include "file_io_tetgen.h"
      48              : #include "file_io_obj.h"
      49              : #include "file_io_lgm.h"
      50              : #include "file_io_lgb.h"
      51              : #include "file_io_ng.h"
      52              : #include "file_io_ug.h"
      53              : #include "file_io_dump.h"
      54              : #include "file_io_ncdf.h"
      55              : #include "file_io_ugx.h"
      56              : #include "file_io_msh.h"
      57              : #include "file_io_stl.h"
      58              : #include "file_io_tikz.h"
      59              : #include "file_io_vtu.h"
      60              : #include "file_io_swc.h"
      61              : #include "file_io_grdecl.h"
      62              : 
      63              : #ifdef UG_PARALLEL
      64              :         #include "pcl/pcl_process_communicator.h"
      65              :         #include "pcl/pcl_util.h"
      66              : #endif
      67              : 
      68              : using namespace std;
      69              : 
      70              : namespace ug
      71              : {
      72              : 
      73              : ////////////////////////////////////////////////////////////////////////////////
      74              : //      this method performs the actual loading.
      75            0 : static bool LoadGrid3d_IMPL(Grid& grid, ISubsetHandler* pSH,
      76              :                                            const char* filename, AVector3& aPos)
      77              : {
      78            0 :         string strExt = GetFilenameExtension(string(filename));
      79            0 :         strExt = ToLower(strExt);
      80              : 
      81              :         bool bAutoassignFaces = false;
      82              :         bool bSuccess = false;
      83            0 :         if(strExt.compare("txt") == 0)
      84              :         {
      85              :                 bAutoassignFaces = true;
      86            0 :                 bSuccess = LoadGridFromTXT(grid, filename, aPos);
      87              :         }
      88            0 :         else if(strExt.compare("grdecl") == 0)
      89              :         {
      90              :                 bAutoassignFaces = true;
      91            0 :                 bSuccess = LoadGridFromGRDECL(grid, filename, aPos);
      92              :         }
      93            0 :         else if(strExt.compare("obj") == 0)
      94            0 :                 bSuccess = LoadGridFromOBJ(grid, filename, aPos, NULL, pSH);
      95            0 :         else if(strExt.compare("lgb") == 0)
      96              :         {
      97              :                 int numSHs = 0;
      98            0 :                 if(pSH)
      99              :                         numSHs = 1;
     100              : 
     101            0 :                 bSuccess = LoadGridFromLGB(grid, filename, &pSH, numSHs, NULL, aPos);
     102              :         }
     103            0 :         else if(strExt.compare("2df") == 0)
     104            0 :                 bSuccess = LoadGridFrom2DF(grid, filename, pSH, aPos);
     105            0 :         else if(strExt.compare("stl") == 0)
     106            0 :                 bSuccess = LoadGridFromSTL(grid, filename, pSH, aPos);
     107            0 :         else if(strExt.compare("net") == 0)
     108            0 :                 bSuccess = LoadGridFromART(grid, filename, pSH, aPos);
     109            0 :         else if(strExt.compare("art") == 0)
     110            0 :                 bSuccess = LoadGridFromART(grid, filename, pSH, aPos);
     111            0 :         else if(strExt.compare("dat") == 0)
     112            0 :                 bSuccess = LoadGridFromART(grid, filename, pSH, aPos);
     113            0 :         else if(strExt.compare("lgm") == 0)
     114            0 :                 bSuccess = ImportGridFromLGM(grid, filename, aPos, pSH);
     115            0 :         else if(strExt.compare("ng") == 0)
     116            0 :                 bSuccess = ImportGridFromNG(grid, filename, aPos, pSH);
     117            0 :         else if(strExt.compare("dump") == 0)
     118              :         {
     119            0 :                 bSuccess = LoadGridFromDUMP(grid, filename, pSH, aPos);
     120              :         }
     121            0 :         else if(strExt.compare("ele") == 0)
     122            0 :                 return LoadGridFromELE(grid, filename, pSH, aPos);
     123            0 :         else if(strExt.compare("msh") == 0)
     124            0 :                 bSuccess = LoadGridFromMSH(grid, filename, pSH, aPos);
     125            0 :         else if(strExt.compare("smesh") == 0)
     126            0 :                 bSuccess = LoadGridFromSMESH(grid, filename, aPos, pSH);
     127            0 :         else if(strExt.compare("asc") == 0){
     128            0 :                 bSuccess = LoadGridFromASC(grid, filename, aPos);
     129              :                 bAutoassignFaces = true;
     130              :         }
     131            0 :         else if(strExt.compare("swc") == 0){
     132            0 :                 bSuccess = LoadGridFromSWC(grid, pSH, filename, aPos);
     133              :         }
     134              : 
     135            0 :         if(bAutoassignFaces && pSH)
     136              :                 pSH->assign_subset(grid.faces_begin(), grid.faces_end(), 0);
     137              : 
     138              :         return bSuccess;
     139              : }
     140              : 
     141              : 
     142            0 : static bool LoadGrid3d(Grid& grid, ISubsetHandler* psh,
     143              :                                            const char* filename, APosition1& aPos)
     144              : {
     145              :         APosition aPosTMP;
     146              :         grid.attach_to_vertices(aPosTMP);
     147            0 :         if(LoadGrid3d_IMPL(grid, psh, filename, aPosTMP)){
     148              :         //      convert the position data from 3d to the required dimension.
     149            0 :                 ConvertMathVectorAttachmentValues<Vertex>(grid, aPosTMP, aPos);
     150              :                 grid.detach_from_vertices(aPosTMP);
     151            0 :                 return true;
     152              :         }
     153              :         grid.detach_from_vertices(aPosTMP);
     154              :         return false;
     155              : }
     156              : 
     157            0 : static bool LoadGrid3d(Grid& grid, ISubsetHandler* psh,
     158              :                                            const char* filename, APosition2& aPos)
     159              : {
     160              :         APosition aPosTMP;
     161              :         grid.attach_to_vertices(aPosTMP);
     162            0 :         if(LoadGrid3d_IMPL(grid, psh, filename, aPosTMP)){
     163              :         //      convert the position data from 3d to the required dimension.
     164            0 :                 ConvertMathVectorAttachmentValues<Vertex>(grid, aPosTMP, aPos);
     165              :                 grid.detach_from_vertices(aPosTMP);
     166            0 :                 return true;
     167              :         }
     168              :         grid.detach_from_vertices(aPosTMP);
     169              :         return false;
     170              : }
     171              : 
     172              : static bool LoadGrid3d(Grid& grid, ISubsetHandler* psh,
     173              :                                            const char* filename, APosition3& aPos)
     174              : {
     175            0 :         return LoadGrid3d_IMPL(grid, psh, filename, aPos);
     176              : }
     177              : 
     178              : ////////////////////////////////////////////////////////////////////////////////
     179              : ///     This method calls specific load routines or delegates loading to LoadGrid3d
     180              : template <class TAPos>
     181            0 : static bool LoadGrid(Grid& grid, ISubsetHandler* psh,
     182              :                                          const char* filename, TAPos& aPos,
     183              :                                          int procId)
     184              : {
     185              : //      For convenience, we support multiple different standard paths, from which
     186              : //      grids may be loaded. We thus first check, where the specified file is
     187              : //      located and load it from that location afterwards.
     188              :         bool loadingGrid = true;
     189              :         #ifdef UG_PARALLEL
     190              :                 if((procId != -1) && (pcl::ProcRank() != procId))
     191              :                         loadingGrid = false;
     192              :         #endif
     193              : 
     194            0 :         grid.message_hub()->post_message(GridMessage_Creation(GMCT_CREATION_STARTS, procId));
     195              :         bool retVal = false;
     196              :         if(loadingGrid){
     197              :         //      Now perform the actual loading.
     198              :         //      first all load methods, which do accept template position types are
     199              :         //      handled. Then all those which only work with 3d position types are processed.
     200            0 :                 string tfile = FindFileInStandardPaths(filename);
     201            0 :                 if(!tfile.empty()){
     202            0 :                         if(tfile.find(".ugx") != string::npos){
     203            0 :                                 if(psh)
     204            0 :                                         retVal = LoadGridFromUGX(grid, *psh, tfile.c_str(), aPos);
     205              :                                 else{
     206              :                                 //      we have to create a temporary subset handler
     207            0 :                                         SubsetHandler shTmp(grid);
     208            0 :                                         retVal = LoadGridFromUGX(grid, shTmp, tfile.c_str(), aPos);
     209            0 :                                 }
     210              :                         }
     211            0 :                         else if(tfile.find(".vtu") != string::npos){
     212            0 :                                 if(psh)
     213            0 :                                         retVal = LoadGridFromVTU(grid, *psh, tfile.c_str(), aPos);
     214              :                                 else{
     215              :                                 //      we have to create a temporary subset handler
     216            0 :                                         SubsetHandler shTmp(grid);
     217            0 :                                         retVal = LoadGridFromVTU(grid, shTmp, tfile.c_str(), aPos);
     218            0 :                                 }
     219              :                         }
     220              :                         else{
     221              :                         //      now we'll handle those methods, which only support 3d position types.
     222            0 :                                 retVal = LoadGrid3d(grid, psh, tfile.c_str(), aPos);
     223              :                         }
     224              :                 }
     225              :         }
     226              :         
     227              :         //      declare global attachments on all processors
     228              :         #ifdef UG_PARALLEL
     229              :                 GlobalAttachments::SynchronizeDeclaredGlobalAttachments(grid, procId);
     230              :         #endif
     231              :         
     232            0 :         grid.message_hub()->post_message(GridMessage_Creation(GMCT_CREATION_STOPS, procId));
     233              :         
     234              :         
     235              :         #ifdef UG_PARALLEL
     236              :                 pcl::ProcessCommunicator procCom;
     237              :                 if(procId == -1)
     238              :                         retVal = pcl::AllProcsTrue(retVal, procCom);
     239              :                 else
     240              :                         retVal = pcl::OneProcTrue(retVal, procCom);
     241              :         #endif
     242              : 
     243            0 :         return retVal;
     244              : }
     245              : 
     246              : template <class TAPos>
     247            0 : static bool LoadGrid(Grid& grid, SPProjectionHandler* ph, size_t& num_ph, ISubsetHandler* psh, std::vector<std::string> additionalSHNames,
     248              :                                                 std::vector<SmartPtr<ISubsetHandler>> ash, const char* filename, TAPos& aPos, int procId)
     249              : {
     250              : //      For convenience, we support multiple different standard paths, from which
     251              : //      grids may be loaded. We thus first check, where the specified file is
     252              : //      located and load it from that location afterwards.
     253              :         bool loadingGrid = true;
     254              :         #ifdef UG_PARALLEL
     255              :                 if((procId != -1) && (pcl::ProcRank() != procId))
     256              :                         loadingGrid = false;
     257              :         #endif
     258              : 
     259            0 :         grid.message_hub()->post_message(GridMessage_Creation(GMCT_CREATION_STARTS, procId));
     260              : 
     261              :         bool retVal = false;
     262              :         if(loadingGrid){
     263              :         //      Now perform the actual loading.
     264              :         //      first all load methods, which do accept template position types are
     265              :         //      handled. Then all those which only work with 3d position types are processed.
     266            0 :                 string tfile = FindFileInStandardPaths(filename);
     267            0 :                 if(!tfile.empty()){
     268            0 :                         if(tfile.find(".ugx") != string::npos){
     269            0 :                                 if(psh)
     270            0 :                                         retVal = LoadGridFromUGX(grid, *ph, num_ph, *psh, additionalSHNames, ash, tfile.c_str(), aPos);
     271              :                                 else{
     272              :                                 //      we have to create a temporary subset handler
     273            0 :                                         SubsetHandler shTmp(grid);
     274            0 :                                         retVal = LoadGridFromUGX(grid, *ph, num_ph, shTmp, additionalSHNames, ash, tfile.c_str(), aPos);
     275            0 :                                 }
     276              :                         }
     277              : 
     278            0 :                         else if(tfile.find(".vtu") != string::npos){
     279            0 :                                 if(psh)
     280            0 :                                         retVal = LoadGridFromVTU(grid, *psh, tfile.c_str(), aPos);
     281              :                                 else{
     282              :                                 //      we have to create a temporary subset handler
     283            0 :                                         SubsetHandler shTmp(grid);
     284            0 :                                         retVal = LoadGridFromVTU(grid, shTmp, tfile.c_str(), aPos);
     285            0 :                                 }
     286              :                         }
     287              :                         else{
     288              :                         //      now we'll handle those methods, which only support 3d position types.
     289            0 :                                 retVal = LoadGrid3d(grid, psh, tfile.c_str(), aPos);
     290              :                         }
     291              : 
     292              :                 }
     293              :         }
     294              :         
     295              :         //      declare global attachments on all processors
     296              :         #ifdef UG_PARALLEL
     297              :                 GlobalAttachments::SynchronizeDeclaredGlobalAttachments(grid, procId);
     298              :         #endif
     299              : 
     300            0 :         grid.message_hub()->post_message(GridMessage_Creation(GMCT_CREATION_STOPS, procId));
     301              :         
     302              :         #ifdef UG_PARALLEL
     303              :                 pcl::ProcessCommunicator procCom;
     304              :                 if(procId == -1)
     305              :                         retVal = pcl::AllProcsTrue(retVal, procCom);
     306              :                 else
     307              :                 {
     308              :                         procCom.broadcast(num_ph, procId);
     309              :                         retVal = pcl::OneProcTrue(retVal, procCom);
     310              :                 }
     311              :         #endif
     312              : 
     313            0 :         return retVal;
     314              : }
     315              : 
     316              : ////////////////////////////////////////////////////////////////////////////////
     317              : template <class TAPos>
     318            0 : bool LoadGridFromFile(Grid& grid, SPProjectionHandler& ph, size_t& num_ph, ISubsetHandler& sh, vector<string> additionalSHNames,
     319              :                                                 vector<SmartPtr<ISubsetHandler>> ash, const char* filename, TAPos& aPos, int procId)
     320              : {
     321            0 :         return LoadGrid(grid, &ph, num_ph, &sh, additionalSHNames, ash, filename, aPos, procId);
     322              : }
     323              : 
     324              : template <class TAPos>
     325            0 : bool LoadGridFromFile(Grid& grid, ISubsetHandler& sh,
     326              :                                           const char* filename, TAPos& aPos, int procId)
     327              : {
     328            0 :         return LoadGrid(grid, &sh, filename, aPos, procId);
     329              : }
     330              : 
     331              : template <class TAPos>
     332            0 : bool LoadGridFromFile(Grid& grid, const char* filename, TAPos& aPos, int procId)
     333              : {
     334            0 :         return LoadGrid(grid, NULL, filename, aPos, procId);
     335              : }
     336              : 
     337            0 : bool LoadGridFromFile(Grid& grid, ISubsetHandler& sh, const char* filename, int procId)
     338              : {
     339            0 :         return LoadGrid(grid, &sh, filename, aPosition, procId);
     340              : }
     341              : 
     342            0 : bool LoadGridFromFile(Grid& grid, const char* filename, int procId)
     343              : {
     344            0 :         return LoadGrid(grid, NULL, filename, aPosition, procId);
     345              : }
     346              : 
     347              : 
     348              : ////////////////////////////////////////////////////////////////////////////////
     349              : ////////////////////////////////////////////////////////////////////////////////
     350              : //      this method performs the actual save.
     351            0 : static bool SaveGrid3d_IMPL(Grid& grid, ISubsetHandler* pSH,
     352              :                                                         const char* filename, AVector3& aPos)
     353              : {
     354            0 :         string strName = filename;
     355            0 :         if(strName.find(".txt") != string::npos)
     356            0 :                 return SaveGridToTXT(grid, filename, aPos);
     357            0 :         if(strName.find(".2df") != string::npos)
     358            0 :                 return SaveGridTo2DF(grid, filename, pSH, aPos);
     359            0 :         else if(strName.find(".obj") != string::npos)
     360            0 :                 return SaveGridToOBJ(grid, filename, aPos, NULL, pSH);
     361            0 :         else if(strName.find(".lgb") != string::npos)
     362              :         {
     363              :                 int numSHs = 0;
     364            0 :                 if(pSH)
     365              :                         numSHs = 1;
     366              : 
     367            0 :                 return SaveGridToLGB(grid, filename, &pSH, numSHs, NULL, aPos);
     368              :         }
     369            0 :         else if(strName.find(".ele") != string::npos)
     370            0 :                 return SaveGridToELE(grid, filename, pSH, aPos);
     371            0 :         else if(strName.find(".net") != string::npos)
     372            0 :                 return SaveGridToART(grid, filename, pSH, aPos);
     373            0 :         else if(strName.find(".art") != string::npos)
     374            0 :                 return SaveGridToART(grid, filename, pSH, aPos);
     375            0 :         else if(strName.find(".ncdf") != string::npos)
     376            0 :                 return SaveGridToNCDF(grid, filename, pSH, aPos);
     377            0 :         else if(strName.find(".stl") != string::npos)
     378            0 :                 return SaveGridToSTL(grid, filename, pSH, aPos);
     379            0 :         else if(strName.find(".smesh") != string::npos)
     380            0 :                 return ExportGridToSMESH(grid, filename, aPos, pSH);
     381              :         else if((strName.find(".tikz") != string::npos)
     382            0 :                         || (strName.find(".tex") != string::npos))
     383              :         {
     384            0 :                 return ExportGridToTIKZ(grid, filename, pSH, aPos);
     385              :         }
     386            0 :         else if (strName.find(".swc") != string::npos)
     387            0 :                 return ExportGridToSWC(grid, pSH, filename, aPos);
     388              : 
     389              :         return false;
     390              : }
     391              : 
     392              : ////////////////////////////////////////////////////////////////////////////////
     393            0 : static bool SaveGrid3d(Grid& grid, ISubsetHandler* psh,
     394              :                                            const char* filename, APosition1& aPos)
     395              : {
     396              :         APosition aPosTMP;
     397              :         grid.attach_to_vertices(aPosTMP);
     398              : //      convert the position data from the given dimension to 3d
     399            0 :         ConvertMathVectorAttachmentValues<Vertex>(grid, aPos, aPosTMP);
     400            0 :         if(SaveGrid3d_IMPL(grid, psh, filename, aPosTMP)){
     401              :                 grid.detach_from_vertices(aPosTMP);
     402            0 :                 return true;
     403              :         }
     404              :         grid.detach_from_vertices(aPosTMP);
     405              :         return false;
     406              : }
     407              : 
     408              : ////////////////////////////////////////////////////////////////////////////////
     409            0 : static bool SaveGrid3d(Grid& grid, ISubsetHandler* psh,
     410              :                                            const char* filename, APosition2& aPos)
     411              : {
     412              :         APosition aPosTMP;
     413              :         grid.attach_to_vertices(aPosTMP);
     414              : //      convert the position data from the given dimension to 3d
     415            0 :         ConvertMathVectorAttachmentValues<Vertex>(grid, aPos, aPosTMP);
     416            0 :         if(SaveGrid3d_IMPL(grid, psh, filename, aPosTMP)){
     417              :                 grid.detach_from_vertices(aPosTMP);
     418            0 :                 return true;
     419              :         }
     420              :         grid.detach_from_vertices(aPosTMP);
     421              :         return false;
     422              : }
     423              : 
     424              : ////////////////////////////////////////////////////////////////////////////////
     425              : static bool SaveGrid3d(Grid& grid, ISubsetHandler* psh,
     426              :                                            const char* filename, APosition3& aPos)
     427              : {
     428            0 :         return SaveGrid3d_IMPL(grid, psh, filename, aPos);
     429              : }
     430              : 
     431              : ////////////////////////////////////////////////////////////////////////////////
     432              : template <class TAPos>
     433            0 : static bool SaveGrid(Grid& grid, ISubsetHandler* psh,
     434              :                                          const char* filename, TAPos& aPos)
     435              : {
     436            0 :         string strName = filename;
     437            0 :         if(strName.find(".ugx") != string::npos){
     438              :                  #if (defined UG_PARALLEL && defined UG_DEBUG)
     439              :                  std::size_t found=strName.find(".ugx");
     440              :                  strName=strName.replace(found, 4, "");
     441              :                  int procRank=pcl::ProcRank();
     442              :                  strName=strName.append("_p");
     443              :                  strName=strName.append(std::to_string(procRank));
     444              :                  strName.append(".ugx");   
     445              :                 #endif
     446              :                 
     447            0 :                 if(psh)
     448            0 :                         return SaveGridToUGX(grid, *psh, strName.c_str(), aPos);
     449              :                 else {
     450            0 :                         SubsetHandler shTmp(grid);
     451            0 :                         return SaveGridToUGX(grid, shTmp, strName.c_str(), aPos);
     452            0 :                 }
     453              :         }
     454            0 :         else if(strName.find(".vtu") != string::npos){
     455              :                 #if (defined UG_PARALLEL && defined UG_DEBUG)
     456              :                  std::size_t found=strName.find(".vtu");
     457              :                          strName=strName.replace(found, 4, "");
     458              :                                  strName=strName.append("_p");
     459              :                  strName=strName.append(std::to_string(pcl::ProcRank()));
     460              :                  strName.append(".vtu");
     461              :                 #endif
     462            0 :                 return SaveGridToVTU(grid, psh, strName.c_str(), aPos);
     463              :         }
     464              :         else
     465            0 :                 return SaveGrid3d(grid, psh, filename, aPos);
     466              : }
     467              : 
     468              : 
     469              : ////////////////////////////////////////////////////////////////////////////////
     470              : template <class TAPos>
     471            0 : bool SaveGridToFile(Grid& grid, ISubsetHandler& sh,
     472              :                                         const char* filename, TAPos& aPos)
     473              : {
     474            0 :         return SaveGrid(grid, &sh, filename, aPos);
     475              : }
     476              : 
     477              : template <class TAPos>
     478            0 : bool SaveGridToFile(Grid& grid, const char* filename, TAPos& aPos)
     479              : {
     480            0 :         return SaveGrid(grid, NULL, filename, aPos);
     481              : }
     482              : 
     483            0 : bool SaveGridToFile(Grid& grid, ISubsetHandler& sh, const char* filename)
     484              : {
     485              : //      check whether one of the standard attachments is attached and call
     486              : //      SaveGrid with that attachment
     487            0 :         if(grid.has_vertex_attachment(aPosition))
     488            0 :                 return SaveGrid(grid, &sh, filename, aPosition);
     489            0 :         if(grid.has_vertex_attachment(aPosition2))
     490            0 :                 return SaveGrid(grid, &sh, filename, aPosition2);
     491            0 :         if(grid.has_vertex_attachment(aPosition1))
     492            0 :                 return SaveGrid(grid, &sh, filename, aPosition1);
     493              : 
     494              :         return false;
     495              : }
     496              : 
     497            0 : bool SaveGridToFile(Grid& grid, const char* filename)
     498              : {
     499              : //      check whether one of the standard attachments is attached and call
     500              : //      SaveGrid with that attachment
     501            0 :         if(grid.has_vertex_attachment(aPosition))
     502            0 :                 return SaveGrid(grid, NULL, filename, aPosition);
     503            0 :         if(grid.has_vertex_attachment(aPosition2))
     504            0 :                 return SaveGrid(grid, NULL, filename, aPosition2);
     505            0 :         if(grid.has_vertex_attachment(aPosition1))
     506            0 :                 return SaveGrid(grid, NULL, filename, aPosition1);
     507              :         return false;
     508              : }
     509              : 
     510            0 : bool SaveGridHierarchyTransformed(MultiGrid& mg, ISubsetHandler& sh,
     511              :                                                                   const char* filename, number offset)
     512              : {
     513              :         PROFILE_FUNC_GROUP("grid");
     514              :         APosition aPos;
     515              : //      uses auto-attach
     516            0 :         Grid::AttachmentAccessor<Vertex, APosition> aaPos(mg, aPos, true);
     517              : 
     518              : //      copy the existing position to aPos. We take care of dimension differences.
     519              : //      Note:   if the method was implemented for domains, this could be implemented
     520              : //                      in a nicer way.
     521            0 :         if(mg.has_vertex_attachment(aPosition))
     522            0 :                 ConvertMathVectorAttachmentValues<Vertex>(mg, aPosition, aPos);
     523            0 :         else if(mg.has_vertex_attachment(aPosition2))
     524            0 :                 ConvertMathVectorAttachmentValues<Vertex>(mg, aPosition2, aPos);
     525            0 :         else if(mg.has_vertex_attachment(aPosition1))
     526            0 :                 ConvertMathVectorAttachmentValues<Vertex>(mg, aPosition1, aPos);
     527              : 
     528              : //      iterate through all vertices and apply an offset depending on their level.
     529            0 :         for(size_t lvl = 0; lvl < mg.num_levels(); ++lvl){
     530            0 :                 for(VertexIterator iter = mg.begin<Vertex>(lvl);
     531            0 :                         iter != mg.end<Vertex>(lvl); ++iter)
     532              :                 {
     533            0 :                         aaPos[*iter].z() += (number)lvl * offset;
     534              :                 }
     535              :         }
     536              : 
     537              : //      finally save the grid
     538              :         bool writeSuccess = SaveGridToFile(mg, sh, filename, aPos);
     539              : 
     540              : //      clean up
     541              :         mg.detach_from_vertices(aPos);
     542              : 
     543            0 :         return writeSuccess;
     544              : }
     545              : 
     546            0 : bool SaveGridHierarchyTransformed(MultiGrid& mg, const char* filename,
     547              :                                                                           number offset)
     548              : {
     549              :         PROFILE_FUNC_GROUP("grid");
     550              : //      cast away constness
     551              :         SubsetHandler& sh = mg.get_hierarchy_handler();
     552              : 
     553              :         APosition aPos;
     554              : //      uses auto-attach
     555            0 :         Grid::AttachmentAccessor<Vertex, APosition> aaPos(mg, aPos, true);
     556              : 
     557              : //      copy the existing position to aPos. We take care of dimension differences.
     558              : //      Note:   if the method was implemented for domains, this could be implemented
     559              : //                      in a nicer way.
     560            0 :         if(mg.has_vertex_attachment(aPosition))
     561            0 :                 ConvertMathVectorAttachmentValues<Vertex>(mg, aPosition, aPos);
     562            0 :         else if(mg.has_vertex_attachment(aPosition2))
     563            0 :                 ConvertMathVectorAttachmentValues<Vertex>(mg, aPosition2, aPos);
     564            0 :         else if(mg.has_vertex_attachment(aPosition1))
     565            0 :                 ConvertMathVectorAttachmentValues<Vertex>(mg, aPosition1, aPos);
     566              : 
     567              : //      iterate through all vertices and apply an offset depending on their level.
     568            0 :         for(size_t lvl = 0; lvl < mg.num_levels(); ++lvl){
     569            0 :                 for(VertexIterator iter = mg.begin<Vertex>(lvl);
     570            0 :                         iter != mg.end<Vertex>(lvl); ++iter)
     571              :                 {
     572            0 :                         aaPos[*iter].z() += (number)lvl * offset;
     573              :                 }
     574              :         }
     575              : 
     576              : //      finally save the grid
     577            0 :         bool writeSuccess = SaveGridToFile(mg, sh, filename, aPos);
     578              : 
     579              : //      clean up
     580              :         mg.detach_from_vertices(aPos);
     581              : 
     582            0 :         return writeSuccess;
     583              : }
     584              : 
     585              : template <class TElem>
     586            0 : static void AssignSubsetsByInterfaceType(SubsetHandler& sh, MultiGrid& mg)
     587              : {
     588              :         const int siNormal = 0;
     589              :         const int siHMaster = 1;
     590              :         const int siHSlave = 1 << 1;
     591              :         const int siVMaster = 1 << 2;
     592              :         const int siVSlave = 1 << 3;
     593              : 
     594            0 :         const char* subsetNames[] = {"normal", "hmaster", "hslave", "hslave+hmaster",
     595              :                                                   "vmaster", "vmaster+hmaster", "vmaster+hslave",
     596              :                                                   "vmaster+hslave+hmaster", "vslave", "vslave+hmaster",
     597              :                                                   "vslave+hslave", "vslave+hslave+hmaster",
     598              :                                                   "vslave+vmaster", "vslave+vmaster+hmaster",
     599              :                                                   "vslave+vmaster+hslave", "vslave+vmaster+hmaster+hslave"};
     600              : 
     601            0 :         for(int i = 0; i < 16; ++i)
     602            0 :                 sh.subset_info(i).name = subsetNames[i];
     603              : 
     604              :         typedef typename Grid::traits<TElem>::iterator TIter;
     605            0 :         for(TIter iter = mg.begin<TElem>(); iter != mg.end<TElem>(); ++iter){
     606              :                 int status = ES_NONE;
     607              : 
     608              :                 #ifdef UG_PARALLEL
     609              :                         DistributedGridManager* distGridMgr = mg.distributed_grid_manager();
     610              :                         if(distGridMgr)
     611              :                                 status = distGridMgr->get_status(*iter);
     612              :                 #endif
     613              : 
     614              :                 int index = siNormal;
     615              :                 if(status & ES_H_MASTER)
     616              :                         index |= siHMaster;
     617              :                 if(status & ES_H_SLAVE)
     618              :                         index |= siHSlave;
     619              :                 if(status & ES_V_MASTER)
     620              :                         index |= siVMaster;
     621              :                 if(status & ES_V_SLAVE)
     622              :                         index |= siVSlave;
     623              : 
     624            0 :                 sh.assign_subset(*iter, index);
     625              :         }
     626            0 : }
     627              : 
     628            0 : bool SaveParallelGridLayout(MultiGrid& mg, const char* filename, number offset)
     629              : {
     630              :         PROFILE_FUNC_GROUP("grid");
     631              : 
     632              :         APosition aPos;
     633              : //      uses auto-attach
     634            0 :         Grid::AttachmentAccessor<Vertex, APosition> aaPos(mg, aPos, true);
     635              : 
     636              : //      copy the existing position to aPos. We take care of dimension differences.
     637              : //      Note:   if the method was implemented for domains, this could be implemented
     638              : //                      in a nicer way.
     639            0 :         if(mg.has_vertex_attachment(aPosition))
     640            0 :                 ConvertMathVectorAttachmentValues<Vertex>(mg, aPosition, aPos);
     641            0 :         else if(mg.has_vertex_attachment(aPosition2))
     642            0 :                 ConvertMathVectorAttachmentValues<Vertex>(mg, aPosition2, aPos);
     643            0 :         else if(mg.has_vertex_attachment(aPosition1))
     644            0 :                 ConvertMathVectorAttachmentValues<Vertex>(mg, aPosition1, aPos);
     645              : 
     646              : //      iterate through all vertices and apply an offset depending on their level.
     647            0 :         for(size_t lvl = 0; lvl < mg.num_levels(); ++lvl){
     648            0 :                 for(VertexIterator iter = mg.begin<Vertex>(lvl);
     649            0 :                         iter != mg.end<Vertex>(lvl); ++iter)
     650              :                 {
     651            0 :                         aaPos[*iter].z() += (number)lvl * offset;
     652              :                 }
     653              :         }
     654              : 
     655              : //      create a subset handler which holds different subsets for the different interface types
     656            0 :         SubsetHandler sh(mg);
     657              : 
     658            0 :         AssignSubsetsByInterfaceType<Vertex>(sh, mg);
     659            0 :         AssignSubsetsByInterfaceType<Edge>(sh, mg);
     660            0 :         AssignSubsetsByInterfaceType<Face>(sh, mg);
     661            0 :         AssignSubsetsByInterfaceType<Volume>(sh, mg);
     662              : 
     663            0 :         AssignSubsetColors(sh);
     664            0 :         EraseEmptySubsets(sh);
     665              : 
     666              : //      finally save the grid
     667              :         bool writeSuccess = SaveGridToFile(mg, sh, filename, aPos);
     668              : 
     669              : //      clean up
     670              :         mg.detach_from_vertices(aPos);
     671              : 
     672            0 :         return writeSuccess;
     673            0 : }
     674              : 
     675              : template <class TElem>
     676            0 : static void AssignSubsetsBySurfaceViewState(SubsetHandler& sh, const SurfaceView& sv,
     677              :                                                                                         MultiGrid& mg)
     678              : {
     679              :         typedef typename Grid::traits<TElem>::iterator TIter;
     680            0 :         for(TIter iter = mg.begin<TElem>(); iter != mg.end<TElem>(); ++iter){
     681              :                 TElem* e = *iter;
     682              : 
     683            0 :                 sh.assign_subset(e, sv.surface_state(e).get());
     684              :         }
     685            0 :         for(int i = 0; i < sh.num_subsets(); ++i)
     686            0 :                 sh.subset_info(i).name = "unknown";
     687            0 :         sh.subset_info(SurfaceView::MG_SHADOW_PURE).name = "shadow-pure";
     688            0 :         sh.subset_info(SurfaceView::MG_SURFACE_PURE).name = "surface-pure";
     689            0 :         sh.subset_info(SurfaceView::MG_SURFACE_RIM).name = "surface-rim";
     690            0 :         sh.subset_info(SurfaceView::MG_SHADOW_RIM_COPY).name = "shadow-rim-copy";
     691            0 :         sh.subset_info(SurfaceView::MG_SHADOW_RIM_NONCOPY).name = "shadow-rim-noncopy";
     692              :         //EraseEmptySubsets(sh);
     693            0 : }
     694              : 
     695            0 : bool SaveSurfaceViewTransformed(MultiGrid& mg, const SurfaceView& sv,
     696              :                                                                 const char* filename, number offset)
     697              : {
     698              :         PROFILE_FUNC_GROUP("grid");
     699              : 
     700              :         APosition aPos;
     701              : //      uses auto-attach
     702            0 :         Grid::AttachmentAccessor<Vertex, APosition> aaPos(mg, aPos, true);
     703              : 
     704              : //      copy the existing position to aPos. We take care of dimension differences.
     705              : //      Note:   if the method was implemented for domains, this could be implemented
     706              : //                      in a nicer way.
     707            0 :         if(mg.has_vertex_attachment(aPosition))
     708            0 :                 ConvertMathVectorAttachmentValues<Vertex>(mg, aPosition, aPos);
     709            0 :         else if(mg.has_vertex_attachment(aPosition2))
     710            0 :                 ConvertMathVectorAttachmentValues<Vertex>(mg, aPosition2, aPos);
     711            0 :         else if(mg.has_vertex_attachment(aPosition1))
     712            0 :                 ConvertMathVectorAttachmentValues<Vertex>(mg, aPosition1, aPos);
     713              : 
     714              : //      iterate through all vertices and apply an offset depending on their level.
     715            0 :         for(size_t lvl = 0; lvl < mg.num_levels(); ++lvl){
     716            0 :                 for(VertexIterator iter = mg.begin<Vertex>(lvl);
     717            0 :                         iter != mg.end<Vertex>(lvl); ++iter)
     718              :                 {
     719            0 :                         aaPos[*iter].z() += (number)lvl * offset;
     720              :                 }
     721              :         }
     722              : 
     723              : //      create a subset handler which holds different subsets for the different interface types
     724            0 :         SubsetHandler sh(mg);
     725              : 
     726            0 :         AssignSubsetsBySurfaceViewState<Vertex>(sh, sv, mg);
     727            0 :         AssignSubsetsBySurfaceViewState<Edge>(sh, sv, mg);
     728            0 :         AssignSubsetsBySurfaceViewState<Face>(sh, sv, mg);
     729            0 :         AssignSubsetsBySurfaceViewState<Volume>(sh, sv, mg);
     730              : 
     731            0 :         AssignSubsetColors(sh);
     732            0 :         EraseEmptySubsets(sh);
     733              : 
     734              : //      finally save the grid
     735              :         bool writeSuccess = SaveGridToFile(mg, sh, filename, aPos);
     736              : 
     737              : //      clean up
     738              :         mg.detach_from_vertices(aPos);
     739              : 
     740            0 :         return writeSuccess;
     741            0 : }
     742              : 
     743              : template<class TElem>
     744            0 : void CopyGridLevelElements(MultiGrid& srcMG, Grid& destGrid,
     745              :                                            ISubsetHandler& srcSH, ISubsetHandler& destSH,
     746              :                                                    int lvl, AVertex& aNewVrt)
     747              : {
     748              :         Grid::VertexAttachmentAccessor<AVertex> aaNewVrt(srcMG, aNewVrt);
     749            0 :         GridObjectCollection goc = srcMG.get_grid_objects();
     750              :         CustomVertexGroup vrts;
     751              : 
     752              :         typedef typename Grid::traits<TElem>::iterator iter_t;
     753              : 
     754            0 :         for(iter_t eIter = goc.begin<TElem>(lvl); eIter != goc.end<TElem>(lvl); ++eIter)
     755              :         {
     756              :                 TElem* e = *eIter;
     757            0 :                 vrts.resize(e->num_vertices());
     758              : 
     759            0 :                 for(size_t iv = 0; iv < e->num_vertices(); ++iv)
     760              :                 {
     761            0 :                         vrts.set_vertex(iv, aaNewVrt[e->vertex(iv)]);
     762              :                 }
     763              : 
     764            0 :                 TElem* ne = *destGrid.create_by_cloning(e, vrts);
     765            0 :                 destSH.assign_subset(ne, srcSH.get_subset_index(e));
     766              :         }
     767            0 : }
     768              : 
     769              : template <class TAPos>
     770            0 : void CopyGridLevel(MultiGrid& srcMG, Grid& destGrid,
     771              :                                    ISubsetHandler& srcSH, ISubsetHandler& destSH,
     772              :                                    int lvl, TAPos aPos)
     773              : {
     774              :         Grid::VertexAttachmentAccessor<TAPos> aaPos(destGrid, aPos);
     775              :         Grid::VertexAttachmentAccessor<TAPos> aaSrcPos(srcMG, aPos);
     776            0 :         GridObjectCollection goc = srcMG.get_grid_objects();
     777              : 
     778              :         AVertex aNewVrt;
     779            0 :         srcMG.attach_to_vertices(aNewVrt);
     780              :         Grid::VertexAttachmentAccessor<AVertex> aaNewVrt(srcMG, aNewVrt);
     781              : 
     782            0 :         for(int si = destSH.num_subsets(); si < srcSH.num_subsets(); ++si)
     783              :         {
     784            0 :                 destSH.subset_info(si) = srcSH.subset_info(si);
     785              :         }
     786              : 
     787            0 :         for(VertexIterator vrtIter = goc.begin<Vertex>(lvl); vrtIter != goc.end<Vertex>(lvl); ++vrtIter)
     788              :         {
     789              :                 Vertex* srcVrt  = *vrtIter;
     790            0 :                 Vertex* destVrt = *destGrid.create_by_cloning(srcVrt);
     791              : 
     792            0 :                 aaNewVrt[srcVrt] = destVrt;
     793              :                 aaPos[destVrt] = aaSrcPos[srcVrt];
     794            0 :                 destSH.assign_subset(destVrt, srcSH.get_subset_index(srcVrt));
     795              :         }
     796              : 
     797            0 :         CopyGridLevelElements<Edge>(srcMG, destGrid, srcSH, destSH, lvl, aNewVrt);
     798            0 :         CopyGridLevelElements<Face>(srcMG, destGrid, srcSH, destSH, lvl, aNewVrt);
     799            0 :         CopyGridLevelElements<Volume>(srcMG, destGrid, srcSH, destSH, lvl, aNewVrt);
     800              : 
     801              :         srcMG.detach_from_vertices(aNewVrt);
     802            0 : }
     803              : 
     804              : template <class TAPos>
     805            0 : void CopyGrid(Grid& srcGrid, Grid& destGrid,
     806              :                           ISubsetHandler& srcSH, ISubsetHandler& destSH,
     807              :                           TAPos aPos)
     808              : {
     809              :         Grid::VertexAttachmentAccessor<TAPos> aaPos(destGrid, aPos);
     810              :         Grid::VertexAttachmentAccessor<TAPos> aaSrcPos(srcGrid, aPos);
     811            0 :         GridObjectCollection goc = srcGrid.get_grid_objects();
     812              : 
     813              :         AVertex aNewVrt;
     814              :         srcGrid.attach_to_vertices(aNewVrt);
     815              :         Grid::VertexAttachmentAccessor<AVertex> aaNewVrt(srcGrid, aNewVrt);
     816              : 
     817            0 :         for(int si = destSH.num_subsets(); si < srcSH.num_subsets(); ++si)
     818              :         {
     819            0 :                 destSH.subset_info(si) = srcSH.subset_info(si);
     820              :         }
     821              : 
     822            0 :         for(VertexIterator vrtIter = goc.begin<Vertex>(); vrtIter != goc.end<Vertex>(); ++vrtIter)
     823              :         {
     824              :                 Vertex* srcVrt  = *vrtIter;
     825            0 :                 Vertex* destVrt = *destGrid.create_by_cloning(srcVrt);
     826            0 :                 aaNewVrt[srcVrt] = destVrt;
     827              :                 aaPos[destVrt] = aaSrcPos[srcVrt];
     828            0 :                 destSH.assign_subset(destVrt, srcSH.get_subset_index(srcVrt));
     829              :         }
     830              : 
     831            0 :         CopyGridElements<Edge>(srcGrid, destGrid, srcSH, destSH, aNewVrt);
     832            0 :         CopyGridElements<Face>(srcGrid, destGrid, srcSH, destSH,  aNewVrt);
     833            0 :         CopyGridElements<Volume>(srcGrid, destGrid, srcSH, destSH, aNewVrt);
     834              : 
     835              :         srcGrid.detach_from_vertices(aNewVrt);
     836            0 : }
     837              : 
     838              : template <class TAPos>
     839            0 : bool SaveGridLevel(MultiGrid& srcMG, ISubsetHandler& srcSH,
     840              :                                    int lvl, const char* filename, TAPos aPos)
     841              : {
     842            0 :         Grid destGrid;
     843            0 :         SubsetHandler destSH(destGrid);
     844              : 
     845            0 :         destGrid.attach_to_vertices(aPos);
     846              : 
     847            0 :         CopyGridLevel(srcMG, destGrid, srcSH, destSH, lvl, aPos);
     848            0 :         SaveGridToFile(destGrid, destSH, filename);
     849              : 
     850            0 :         return true;
     851            0 : }
     852              : 
     853              : template <typename TAPos>
     854            0 : void MergeGrids
     855              : (
     856              :         Grid& mrgGrid,
     857              :         Grid& grid,
     858              :         ISubsetHandler& mrgSH,
     859              :         ISubsetHandler& sh,
     860              :         TAPos aPos,
     861              :         bool joinSubsets
     862              : )
     863              : {
     864              :         // add offset to not join subsets with same index
     865            0 :         int subsetBaseInd = joinSubsets ? 0 : mrgSH.num_subsets();
     866              : 
     867              :         // attach data
     868              :         AVertex aVrt;
     869              :         grid.attach_to_vertices(aVrt);
     870              : 
     871              :         // attachments accessors for position and vertex index
     872            0 :         Grid::AttachmentAccessor<Vertex, TAPos> aaPosMRG(mrgGrid, aPos, true);
     873            0 :         Grid::AttachmentAccessor<Vertex, TAPos> aaPos(grid, aPos, true);
     874              :         Grid::AttachmentAccessor<Vertex, AVertex> aaVrt(grid, aVrt);
     875              : 
     876              :         // copy vertices
     877              :         for (VertexIterator iter = grid.begin<Vertex>();
     878            0 :                         iter != grid.end<Vertex>(); ++iter)
     879              :         {
     880            0 :                 Vertex* nvrt = *mrgGrid.create_by_cloning(*iter);
     881              :                 aaPosMRG[nvrt] = aaPos[*iter];
     882            0 :                 aaVrt[*iter] = nvrt;
     883            0 :                 mrgSH.assign_subset(nvrt, subsetBaseInd + sh.get_subset_index(*iter));
     884              :         }
     885              : 
     886              :         //      copy edges
     887            0 :         EdgeDescriptor ed;
     888              :         for (EdgeIterator iter = grid.begin<Edge>();
     889            0 :                         iter != grid.end<Edge>(); ++iter)
     890              :         {
     891              :                 Edge* eSrc = *iter;
     892            0 :                 ed.set_vertices(aaVrt[eSrc->vertex(0)], aaVrt[eSrc->vertex(1)]);
     893            0 :                 Edge* e = *mrgGrid.create_by_cloning(eSrc, ed);
     894            0 :                 mrgSH.assign_subset(e, subsetBaseInd + sh.get_subset_index(eSrc));
     895              :         }
     896              : 
     897              :         //      copy faces
     898            0 :         FaceDescriptor fd;
     899              :         for (FaceIterator iter = grid.begin<Face>();
     900            0 :                 iter != grid.end<Face>(); ++iter)
     901              :         {
     902              :                 Face* fSrc = *iter;
     903            0 :                 fd.set_num_vertices((uint)fSrc->num_vertices());
     904            0 :                 for (size_t i = 0; i < fd.num_vertices(); ++i) {
     905            0 :                         fd.set_vertex((uint)i, aaVrt[fSrc->vertex(i)]);
     906              :                 }
     907            0 :                 Face* f = *mrgGrid.create_by_cloning(fSrc, fd);
     908            0 :                 mrgSH.assign_subset(f, subsetBaseInd + sh.get_subset_index(fSrc));
     909              :         }
     910              : 
     911              :         // copy volumes
     912            0 :         VolumeDescriptor vd;
     913              :         for (VolumeIterator iter = grid.begin<Volume>();
     914            0 :                         iter != grid.end<Volume>(); ++iter)
     915              :         {
     916              :                 Volume* vSrc = *iter;
     917            0 :                 vd.set_num_vertices((uint)vSrc->num_vertices());
     918            0 :                 for (size_t i = 0; i < vd.num_vertices(); ++i) {
     919            0 :                         vd.set_vertex((uint)i, aaVrt[vSrc->vertex(i)]);
     920              :                 }
     921              : 
     922            0 :                 Volume* v = *mrgGrid.create_by_cloning(vSrc, vd);
     923            0 :                 mrgSH.assign_subset(v, subsetBaseInd + sh.get_subset_index(vSrc));
     924              :         }
     925              : 
     926              :         // remove the temporary attachment
     927              :         mrgGrid.detach_from_vertices(aVrt);
     928              : 
     929              :         // overwrite subset names
     930            0 :         for (int i_sub = 0; i_sub < sh.num_subsets(); ++i_sub){
     931            0 :                 mrgSH.subset_info(subsetBaseInd + i_sub) = sh.subset_info(i_sub);
     932              :         }
     933            0 : }
     934              : 
     935            0 : bool SaveGridLevelToFile(MultiGrid& srcMG, ISubsetHandler& srcSH, int lvl, const char* filename)
     936              : {
     937              : //      check whether one of the standard attachments is attached and call
     938              : //      SaveGridLevel with that attachment
     939              :         /*#ifdef UG_PARALLEL
     940              :             std::size_t found=filename.find(".ugx")
     941              :             if(found != string::npos){
     942              :                 filename=filename.replace(found, 4, "");    
     943              :             }
     944              :             filename=filename.append(std::to_string(pcl::ProRank()));
     945              :             if(found != string::npos){
     946              :                         filename.append(".ugx");
     947              :             }
     948              :         #endif*/
     949            0 :         if(srcMG.has_vertex_attachment(aPosition))
     950            0 :                 return SaveGridLevel(srcMG, srcSH, lvl, filename, aPosition);
     951            0 :         if(srcMG.has_vertex_attachment(aPosition2))
     952            0 :                 return SaveGridLevel(srcMG, srcSH, lvl, filename, aPosition2);
     953            0 :         if(srcMG.has_vertex_attachment(aPosition1))
     954            0 :                 return SaveGridLevel(srcMG, srcSH, lvl, filename, aPosition1);
     955              : 
     956              :         return false;
     957              : }       
     958              : 
     959              : ////////////////////////////////////////////////////////////////////////////////
     960              : ////////////////////////////////////////////////////////////////////////////////
     961              : //      explicit template instantiation
     962              : template bool LoadGridFromFile(Grid&, ISubsetHandler&, const char*, AVector1&, int);
     963              : template bool LoadGridFromFile(Grid&, ISubsetHandler&, const char*, AVector2&, int);
     964              : template bool LoadGridFromFile(Grid&, ISubsetHandler&, const char*, AVector3&, int);
     965              : 
     966              : template bool LoadGridFromFile(Grid&, const char*, AVector1&, int);
     967              : template bool LoadGridFromFile(Grid&, const char*, AVector2&, int);
     968              : template bool LoadGridFromFile(Grid&, const char*, AVector3&, int);
     969              : 
     970              : template bool LoadGridFromFile(Grid&, SPProjectionHandler&, size_t&, ISubsetHandler&, std::vector<std::string>, std::vector<SmartPtr<ISubsetHandler>>, const char*, AVector1&, int);
     971              : template bool LoadGridFromFile(Grid&, SPProjectionHandler&, size_t&, ISubsetHandler&, std::vector<std::string>, std::vector<SmartPtr<ISubsetHandler>>, const char*, AVector2&, int);
     972              : template bool LoadGridFromFile(Grid&, SPProjectionHandler&, size_t&, ISubsetHandler&, std::vector<std::string>, std::vector<SmartPtr<ISubsetHandler>>, const char*, AVector3&, int);
     973              : 
     974              : template bool SaveGridToFile(Grid&, ISubsetHandler&, const char*, AVector1&);
     975              : template bool SaveGridToFile(Grid&, ISubsetHandler&, const char*, AVector2&);
     976              : template bool SaveGridToFile(Grid&, ISubsetHandler&, const char*, AVector3&);
     977              : 
     978              : template bool SaveGridToFile(Grid&, const char*, AVector1&);
     979              : template bool SaveGridToFile(Grid&, const char*, AVector2&);
     980              : template bool SaveGridToFile(Grid&, const char*, AVector3&);
     981              : 
     982              : template void CopyGrid(Grid&, Grid&, ISubsetHandler&, ISubsetHandler&, APosition1);
     983              : template void CopyGrid(Grid&, Grid&, ISubsetHandler&, ISubsetHandler&, APosition2);
     984              : template void CopyGrid(Grid&, Grid&, ISubsetHandler&, ISubsetHandler&, APosition3);
     985              : 
     986              : template void MergeGrids(Grid&, Grid&, ISubsetHandler&, ISubsetHandler&, APosition1, bool);
     987              : template void MergeGrids(Grid&, Grid&, ISubsetHandler&, ISubsetHandler&, APosition2, bool);
     988              : template void MergeGrids(Grid&, Grid&, ISubsetHandler&, ISubsetHandler&, APosition3, bool);
     989              : 
     990              : }//     end of namespace
        

Generated by: LCOV version 2.0-1