From a174cfdd31b106ae5743e03791ef322763386265 Mon Sep 17 00:00:00 2001
From: "LEGOLAS\\lenz" <lenz@irmb.tu-bs.de>
Date: Fri, 16 Nov 2018 10:43:25 +0100
Subject: [PATCH] implements GksMeshAdapter in 3D

---
 CMakeLists.txt                                |   11 +-
 src/GksMeshAdapter/GksMeshAdapter.cpp         | 1525 +++++++++++++++++
 src/GksMeshAdapter/GksMeshAdapter.h           |  151 ++
 src/GksMeshAdapter/MeshCell.cpp               |   32 +
 src/GksMeshAdapter/MeshCell.h                 |   71 +
 src/GksMeshAdapter/MeshFace.cpp               |   12 +
 src/GksMeshAdapter/MeshFace.h                 |   50 +
 src/GksMeshAdapter/package.include            |    0
 targets/apps/GKS/gksTest/CMakeLists.txt       |    6 +-
 targets/apps/GKS/gksTest/main.cpp             | 1161 +------------
 .../libs/GksMeshAdapter/3rdPartyLinking.cmake |    6 +
 targets/libs/GksMeshAdapter/CMakeLists.txt    |   18 +
 .../libs/GksMeshAdapter/CMakePackage.cmake    |    8 +
 13 files changed, 1939 insertions(+), 1112 deletions(-)
 create mode 100644 src/GksMeshAdapter/GksMeshAdapter.cpp
 create mode 100644 src/GksMeshAdapter/GksMeshAdapter.h
 create mode 100644 src/GksMeshAdapter/MeshCell.cpp
 create mode 100644 src/GksMeshAdapter/MeshCell.h
 create mode 100644 src/GksMeshAdapter/MeshFace.cpp
 create mode 100644 src/GksMeshAdapter/MeshFace.h
 create mode 100644 src/GksMeshAdapter/package.include
 create mode 100644 targets/libs/GksMeshAdapter/3rdPartyLinking.cmake
 create mode 100644 targets/libs/GksMeshAdapter/CMakeLists.txt
 create mode 100644 targets/libs/GksMeshAdapter/CMakePackage.cmake

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 02360bd20..c40dec06b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -52,11 +52,16 @@ include_directories(${CMAKE_BINARY_DIR})
 
 set_property(GLOBAL PROPERTY USE_FOLDERS ON)
 set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER ".cmake")
-set(libraryFolder "libs")
+
+set(libraryFolder    "libs")
+set(gksLibraryFolder "libs/GKS")
+
 set(testFolder "tests")
-set(appFolder "apps")
+
+set(appFolder    "apps")
 set(lbmAppFolder "apps/LBM")
 set(gksAppFolder "apps/GKS")
+
 set(thirdPartyFolder "3rdParty")
 
 IF(MSVC)
@@ -123,6 +128,8 @@ add_subdirectory(3rdParty/metis/metis-5.1.0)
 add_subdirectory(targets/libs/VirtualFluidsBasics)
 add_subdirectory(targets/libs/Core)
 
+add_subdirectory(targets/libs/GksMeshAdapter)
+
 if(HULC.BUILD_NUMERIC_TESTS)
  	add_subdirectory(3rdParty/fftw/fftw-3.3.7)
 	add_subdirectory(targets/tests/TestingHULC)
diff --git a/src/GksMeshAdapter/GksMeshAdapter.cpp b/src/GksMeshAdapter/GksMeshAdapter.cpp
new file mode 100644
index 000000000..e67b3fa13
--- /dev/null
+++ b/src/GksMeshAdapter/GksMeshAdapter.cpp
@@ -0,0 +1,1525 @@
+#include "GksMeshAdapter.h"
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+
+#include <fstream>
+#include <algorithm>
+#include <numeric>
+#include <functional>
+#include <iostream>
+#include <iomanip>
+
+#include "core/Logger/Logger.h"
+
+#include "GridGenerator/grid/distributions/D3Q27.h"
+#include "GridGenerator/grid/GridBuilder/MultipleGridBuilder.h"
+#include "GridGenerator/grid/NodeValues.h"
+#include "GridGenerator/utilities/math/Math.h"
+
+#include "MeshCell.h"
+#include "MeshFace.h"
+
+void GksMeshAdapter::inputGrid(SPtr<MultipleGridBuilder> gridBuilder)
+{
+    *logging::out << logging::Logger::INFO_INTERMEDIATE << "inputGrid()" << "\n";
+
+    this->numberOfLevels = gridBuilder->getNumberOfGridLevels();
+
+    std::vector< SPtr<Grid> > grids = gridBuilder->getGrids();
+
+    this->dxCoarse = grids[0]->getDelta();
+
+    //////////////////////////////////////////////////////////////////////////
+
+    this->gridToMesh.resize( gridBuilder->getNumberOfGridLevels() );
+
+    for( uint level = 0; level < gridBuilder->getNumberOfGridLevels(); level++ ){
+        this->gridToMesh[level].resize( grids[level]->getSize() );
+
+        for( auto& cellIdx : this->gridToMesh[level] ) cellIdx = INVALID_INDEX;
+    }
+
+    //////////////////////////////////////////////////////////////////////////
+    //
+    //    I d e n t i f y    C e l l s    i n    L B - G r i d
+    //
+    //////////////////////////////////////////////////////////////////////////
+
+    uint numberOfCells = 0;
+
+    for( uint level = 0; level < gridBuilder->getNumberOfGridLevels(); level++ ){
+        for( uint gridIdx = 0; gridIdx < grids[level]->getSize(); gridIdx++ ){
+            if (grids[level]->getFieldEntry(gridIdx)  != STOPPER_COARSE_UNDER_FINE &&
+                grids[level]->getFieldEntry(gridIdx)  != STOPPER_SOLID &&
+                grids[level]->getFieldEntry(gridIdx)  != INVALID_COARSE_UNDER_FINE &&
+                grids[level]->getFieldEntry(gridIdx)  != INVALID_OUT_OF_GRID &&
+                grids[level]->getFieldEntry(gridIdx)  != INVALID_SOLID )
+            {
+                this->gridToMesh[level][gridIdx] = numberOfCells++;
+            }
+        }
+    }
+    
+    //////////////////////////////////////////////////////////////////////////
+    //
+    //    S e t    M e s h    t o    G r i d    i n f o r m a t i o n
+    //
+    //////////////////////////////////////////////////////////////////////////
+
+    this->cells.resize( numberOfCells );
+
+    for( uint level = 0; level < gridBuilder->getNumberOfGridLevels(); level++ ){
+        for( uint gridIdx = 0; gridIdx < grids[level]->getSize(); gridIdx++ ){
+            if ( this->gridToMesh[level][gridIdx] != INVALID_INDEX ){
+
+                uint cellIdx = gridToMesh[level][gridIdx];
+
+                MeshCell& cell = this->cells[ cellIdx ];
+
+                cell.level   = level;
+                cell.gridIdx = gridIdx;
+
+                cell.type = grids[level]->getFieldEntry(gridIdx);
+            }
+        }
+    }
+
+    //////////////////////////////////////////////////////////////////////////
+}
+
+void GksMeshAdapter::findQuadtreeConnectivity(SPtr<MultipleGridBuilder> gridBuilder)
+{
+    *logging::out << logging::Logger::INFO_INTERMEDIATE << "findQuadtreeConnectivity()" << "\n";
+
+    std::vector< SPtr<Grid> > grids = gridBuilder->getGrids();
+
+    for( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
+    
+        MeshCell& cell = this->cells[ cellIdx ];
+
+        if( cell.type == FLUID_FCC || cell.type == FLUID_CFC ){
+
+            real x, y, z;
+            grids[cell.level]->transIndexToCoords(cell.gridIdx, x, y, z);
+
+            real d = 0.25 * grids[cell.level]->getDelta();
+
+            for( uint idx = 0; idx < 8; idx++ )
+            {
+                Distribution dirs = DistributionHelper::getDistribution27();
+
+                real xSign = dirs.directions[idx + 19][0];
+                real ySign = dirs.directions[idx + 19][1];
+                real zSign = dirs.directions[idx + 19][2];
+
+                cell.children[ idx ] = this->gridToMesh[cell.level+1][ grids[cell.level+1]->transCoordToIndex( x + xSign * d, 
+                                                                                                               y + ySign * d, 
+                                                                                                               z + zSign * d ) ];
+            }
+
+            // register parent
+            for( uint child = 0; child < 8; child++ )
+                this->cells[ cell.children[child] ].parent = cellIdx;
+
+            // set correct type for CFF cells
+            for( uint child = 0; child < 8; child++ )
+                if( this->cells[ cell.children[child] ].type != FLUID_FCF ) 
+                    this->cells[ cell.children[child] ].type = FLUID_CFF;
+
+        }
+    }
+}
+
+void GksMeshAdapter::findCellToCellConnectivity(SPtr<MultipleGridBuilder> gridBuilder)
+{
+    *logging::out << logging::Logger::INFO_INTERMEDIATE << "findCellToCellConnectivity()" << "\n";
+
+    std::vector< SPtr<Grid> > grids = gridBuilder->getGrids();
+
+    for( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
+    
+        MeshCell& cell = this->cells[ cellIdx ];
+
+        real x, y, z;
+        grids[cell.level]->transIndexToCoords(cell.gridIdx, x, y, z);
+
+        real d = grids[cell.level]->getDelta();
+
+        for( uint idx = 0; idx < 27; idx++ )
+        {
+            if( idx == DIR_27_ZERO ) continue;
+
+            Distribution dirs = DistributionHelper::getDistribution27();
+
+            int xSign = dirs.directions[idx][0];
+            int ySign = dirs.directions[idx][1];
+            int zSign = dirs.directions[idx][2];
+
+            uint neighborGridIdx = grids[cell.level]->transCoordToIndex( x + xSign * d, 
+                                                                         y + ySign * d, 
+                                                                         z + zSign * d );
+
+            if( neighborGridIdx == INVALID_INDEX || this->gridToMesh[cell.level][neighborGridIdx] == INVALID_INDEX ){
+                if( !cell.isCoarseGhostCell() && cell.type != BC_SOLID )
+                    cell.isGhostCell = true;
+
+                continue;
+            }
+
+            cell.cellToCell[ idx ] = this->gridToMesh[cell.level][neighborGridIdx];
+        }
+    }
+}
+
+void GksMeshAdapter::countCells()
+{
+    this->numberOfCellsPerLevel    .resize( this->numberOfLevels );
+    this->numberOfBulkCellsPerLevel.resize( this->numberOfLevels );
+    this->startOfCellsPerLevel     .resize( this->numberOfLevels );
+
+    for( auto& i : this->numberOfCellsPerLevel     ) i = 0;
+    for( auto& i : this->numberOfBulkCellsPerLevel ) i = 0;
+    for( auto& i : this->startOfCellsPerLevel      ) i = 0;
+
+    uint level = 0;
+    for( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
+        MeshCell& cell = this->cells[ cellIdx ];
+
+        if( cell.level != level ) level++;
+
+        this->numberOfCellsPerLevel[ level ]++; 
+
+        if( ! ( cell.isGhostCell || cell.isCoarseGhostCell() ) )
+            this->numberOfBulkCellsPerLevel[ level ]++;
+    }
+
+    for( uint level = 1; level < this->numberOfLevels; level++ )
+        this->startOfCellsPerLevel[ level ] = this->startOfCellsPerLevel[ level-1 ] + this->numberOfCellsPerLevel[ level-1 ];
+}
+
+void GksMeshAdapter::partitionCells()
+{
+    for( uint level = 0; level < this->numberOfLevels; level++ ){
+
+        std::vector<uint> idxMap( this->cells.size() );
+        std::iota( idxMap.begin(), idxMap.end(), 0 );
+
+        // partition idxMap
+        std::stable_partition(  idxMap.begin() + this->startOfCellsPerLevel[level], 
+                                idxMap.begin() + this->startOfCellsPerLevel[level] 
+                                               + this->numberOfCellsPerLevel[level], 
+                                [this](int lhs){ 
+                                    return ! ( this->cells[ lhs ].isGhostCell || this->cells[ lhs ].isCoarseGhostCell() );
+                                }
+                             );
+
+        // invert idxMap
+        {
+            std::vector<uint> buffer = idxMap;
+            for( uint idx = 0; idx < idxMap.size(); idx ++ )
+                idxMap[ buffer[idx] ] = idx;
+        }
+
+        // partition cell list
+        std::stable_partition(  this->cells.begin() + this->startOfCellsPerLevel[level], 
+                                this->cells.begin() + this->startOfCellsPerLevel[level] 
+                                                    + this->numberOfCellsPerLevel[level], 
+                                [this](MeshCell lhs){ 
+                                    return ! ( lhs.isGhostCell || lhs.isCoarseGhostCell() );
+                                }
+                             );
+
+        this->refreshCellConnectivity( idxMap );
+    }
+}
+
+void GksMeshAdapter::refreshCellConnectivity(const std::vector<uint>& idxMap)
+{
+    for( auto& cell : this->cells ){
+        for( uint idx = 0; idx < 27; idx++ )
+            if( cell.cellToCell[ idx ] != INVALID_INDEX )
+                cell.cellToCell[ idx ] = idxMap[ cell.cellToCell[ idx ] ];
+
+        if( cell.parent != INVALID_INDEX )
+            cell.parent = idxMap[ cell.parent ];
+
+        for( uint idx = 0; idx < 8; idx++ )
+            if( cell.children[ idx ] != INVALID_INDEX )
+                cell.children[ idx ] = idxMap[ cell.children[ idx ] ];
+    }
+
+    for( auto& grid : this->gridToMesh ){
+        for( auto& cellIdx : grid ){
+            if( cellIdx != INVALID_INDEX )
+                cellIdx = idxMap[ cellIdx ];
+        }
+    }
+}
+
+void GksMeshAdapter::findCornerCells(SPtr<MultipleGridBuilder> gridBuilder, real z0)
+{
+    //SPtr<Grid> grid = gridBuilder->getGrids()[0];
+    //
+    //this->cornerCells[0] = this->gridToMesh[ 0 ][ grid->transCoordToIndex( grid->getStartX(), grid->getStartY(), z0 ) ];
+    //this->cornerCells[1] = this->gridToMesh[ 0 ][ grid->transCoordToIndex( grid->getEndX()  , grid->getStartY(), z0 ) ];
+    //this->cornerCells[2] = this->gridToMesh[ 0 ][ grid->transCoordToIndex( grid->getEndX()  , grid->getEndY()  , z0 ) ];
+    //this->cornerCells[3] = this->gridToMesh[ 0 ][ grid->transCoordToIndex( grid->getStartX(), grid->getEndY()  , z0 ) ];
+}
+
+void GksMeshAdapter::generateNodes(SPtr<MultipleGridBuilder> gridBuilder)
+{
+    *logging::out << logging::Logger::INFO_INTERMEDIATE << "generateNodes()" << "\n";
+
+    std::vector< SPtr<Grid> > grids = gridBuilder->getGrids();
+
+    nodes.reserve( 2 * this->cells.size() );
+
+    for( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
+    
+        MeshCell& cell = this->cells[ cellIdx ];
+
+        if( cell.type == STOPPER_SOLID ) continue;
+
+        real x, y, z;
+        grids[cell.level]->transIndexToCoords(cell.gridIdx, x, y, z);
+
+        real d = 0.5 * grids[cell.level]->getDelta();
+
+        std::array<Vec3,8> dir;
+
+        for( uint idx = 0; idx < 8; idx++ )
+        {
+            if( cell.cellToNode[idx] == INVALID_INDEX )
+            {
+                Distribution dirs = DistributionHelper::getDistribution27();
+
+                real dx = dirs.directions[idx + 19][0] * d;
+                real dy = dirs.directions[idx + 19][1] * d;
+                real dz = dirs.directions[idx + 19][2] * d;
+
+                nodes.push_back( Vec3( x + dx, y + dy, z + dz ) );
+
+                cell.cellToNode[idx] = nodes.size()-1;
+
+                // register new node at neighbor cells on same level
+                for( uint idx = 0; idx < 8; idx++ )
+                {
+                    if( cell.cellToCell[idx] == INVALID_INDEX ) continue;
+
+                    Distribution dirs = DistributionHelper::getDistribution27();
+
+                    real dxNeighbor = - dirs.directions[idx + 19][0] * d;
+                    real dyNeighbor = - dirs.directions[idx + 19][1] * d;
+                    real dzNeighbor = - dirs.directions[idx + 19][2] * d;
+                    
+                    real xNeighbor = nodes.back().x + dx + dxNeighbor;
+                    real yNeighbor = nodes.back().y + dy + dyNeighbor;
+                    real zNeighbor = nodes.back().z + dz + dzNeighbor;
+
+                    uint neighborGridIdx = grids[cell.level]->transCoordToIndex( xNeighbor, yNeighbor, zNeighbor );
+
+                    if( neighborGridIdx != INVALID_INDEX && gridToMesh[ cell.level ][ neighborGridIdx ] == cell.cellToCell[idx] )
+                    {
+                        this->cells[ cell.cellToCell[idx] ].cellToNode[ idx ];
+                    }
+                }
+            }
+        }
+
+        //////////////////////////////////////////////////////////////////////////
+
+        //if( cell.type == FLUID_FCC || cell.type == FLUID_CFC ){
+
+        //    // register edge nodes at child cells
+        //    this->cells[ cell.children[0] ].cellToNode[0] = cell.cellToNode[0];
+        //    this->cells[ cell.children[1] ].cellToNode[1] = cell.cellToNode[1];
+        //    this->cells[ cell.children[2] ].cellToNode[2] = cell.cellToNode[2];
+        //    this->cells[ cell.children[3] ].cellToNode[3] = cell.cellToNode[3];                    
+
+        //    std::array<arraytypes::Vec2,4> dir;
+
+        //    dir[0] = arraytypes::Vec2( - d, 0.0 );
+        //    dir[1] = arraytypes::Vec2( 0.0, - d );
+        //    dir[2] = arraytypes::Vec2(   d, 0.0 );
+        //    dir[3] = arraytypes::Vec2( 0.0,   d );
+
+        //    // introduce new face nodes
+        //    if( cell.cellToFaceNode[0] == -1 ){
+        //        nodes.push_back( arraytypes::Vec2( x + dir[0].x, y + dir[0].y ) );
+
+        //        cell.cellToFaceNode[0] = nodes.size()-1;
+        //            
+        //        // register face node at adjacent cell
+        //        if( cell.cellToCell[0] != -1 ) this->cells[ cell.cellToCell[0] ].cellToFaceNode[2] = nodes.size()-1;
+
+        //    }
+        //            
+        //    if( cell.cellToFaceNode[1] == -1 ){
+        //        nodes.push_back( arraytypes::Vec2( x + dir[1].x, y + dir[1].y ) );
+
+        //        cell.cellToFaceNode[1] = nodes.size()-1;
+        //            
+        //        // register face node at adjacent cell
+        //        if( cell.cellToCell[1] != -1 ) this->cells[ cell.cellToCell[1] ].cellToFaceNode[3] = nodes.size()-1;
+
+        //    }
+        //            
+        //    if( cell.cellToFaceNode[2] == -1 ){
+        //        nodes.push_back( arraytypes::Vec2( x + dir[2].x, y + dir[2].y ) );
+
+        //        cell.cellToFaceNode[2] = nodes.size()-1;
+        //            
+        //        // register face node at adjacent cell
+        //        if( cell.cellToCell[2] != -1 ) this->cells[ cell.cellToCell[2] ].cellToFaceNode[0] = nodes.size()-1;
+
+        //    }
+        //            
+        //    if( cell.cellToFaceNode[3] == -1 ){
+        //        nodes.push_back( arraytypes::Vec2( x + dir[3].x, y + dir[3].y ) );
+
+        //        cell.cellToFaceNode[3] = nodes.size()-1;
+        //            
+        //        // register face node at adjacent cell
+        //        if( cell.cellToCell[3] != -1 ) this->cells[ cell.cellToCell[3] ].cellToFaceNode[1] = nodes.size()-1;
+
+        //    }
+
+        //    // register face node at child cells
+        //    this->cells[ cell.children[3] ].cellToNode[0] = cell.cellToFaceNode[0];
+        //    this->cells[ cell.children[0] ].cellToNode[3] = cell.cellToFaceNode[0];
+
+        //    this->cells[ cell.children[0] ].cellToNode[1] = cell.cellToFaceNode[1];
+        //    this->cells[ cell.children[1] ].cellToNode[0] = cell.cellToFaceNode[1];
+
+        //    this->cells[ cell.children[1] ].cellToNode[2] = cell.cellToFaceNode[2];
+        //    this->cells[ cell.children[2] ].cellToNode[1] = cell.cellToFaceNode[2];
+
+        //    this->cells[ cell.children[2] ].cellToNode[3] = cell.cellToFaceNode[3];
+        //    this->cells[ cell.children[3] ].cellToNode[2] = cell.cellToFaceNode[3];
+        //}
+    }
+}
+
+void GksMeshAdapter::inputQs(SPtr<MultipleGridBuilder> gridBuilder)
+{
+
+    //std::vector< SPtr<Grid> > grids = gridBuilder->getGrids();
+
+    //for( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
+
+    //    MeshCell& cell = this->cells[ cellIdx ];
+
+    //    if( cell.type != BC_SOLID ) continue;
+
+    //    cell.Qs[0] = grids[cell.level]->getQValue(cell.gridIdx, 7);
+    //    cell.Qs[1] = grids[cell.level]->getQValue(cell.gridIdx, 8);
+    //    cell.Qs[2] = grids[cell.level]->getQValue(cell.gridIdx, 6);
+    //    cell.Qs[3] = grids[cell.level]->getQValue(cell.gridIdx, 9);
+    //}
+}
+
+void GksMeshAdapter::morphNodes()
+{
+    //this->displacement.resize(   this->nodes.size() );
+    //this->nDisplacements.resize( this->nodes.size() );
+
+    //for( uint n : this->nDisplacements ) n = 0;
+
+    //for( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
+
+    //    MeshCell& cell = this->cells[ cellIdx ];
+
+    //    if( cell.type != BC_SOLID ) continue;
+
+    //    std::array<arraytypes::Vec2,4> dir;
+    //    dir[0] = arraytypes::Vec2( - getDx(cell.level), - getDx(cell.level) );
+    //    dir[1] = arraytypes::Vec2(   getDx(cell.level), - getDx(cell.level) );
+    //    dir[2] = arraytypes::Vec2(   getDx(cell.level),   getDx(cell.level) );
+    //    dir[3] = arraytypes::Vec2( - getDx(cell.level),   getDx(cell.level) );
+
+    //    for( uint idx = 0; idx < 4; idx ++ ){
+    //    
+    //        //if( vf::Math::equal( cell.Qs[idx], 0.0 ) ) continue;
+    //        if( cell.Qs[idx] < 0.0 || cell.Qs[idx] > 1.0 ) continue;
+
+    //        this->displacement[ cell.cellToNode[idx] ].x += ( cell.Qs[idx] - 0.5 ) * dir[idx].x;
+    //        this->displacement[ cell.cellToNode[idx] ].y += ( cell.Qs[idx] - 0.5 ) * dir[idx].y;
+    //    
+    //        this->nDisplacements[ cell.cellToNode[idx] ]++;
+    //    }
+    //}
+
+    //for( uint nodeIdx = 0; nodeIdx < this->nodes.size(); nodeIdx++ ){
+    //
+    //    if( this->nDisplacements[nodeIdx] == 0 ) continue;
+    //
+    //    nodes[ nodeIdx ].x += this->displacement[ nodeIdx ].x / double( this->nDisplacements[ nodeIdx ] );
+    //    nodes[ nodeIdx ].y += this->displacement[ nodeIdx ].y / double( this->nDisplacements[ nodeIdx ] );
+    //}
+}
+
+void GksMeshAdapter::repairTriangularCells()
+{
+    //for( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
+
+    //    MeshCell& cell = this->cells[ cellIdx ];
+
+    //    if( cell.type != BC_SOLID ) continue;
+
+    //    arraytypes::uint4 cellToNodeTMP = cell.cellToNode;
+
+    //    for( uint idx = 0; idx < 4; idx++ ){
+    //    
+    //        arraytypes::Vec2 v1, v2;
+
+    //        v1.x =   this->nodes[ cell.cellToNode[ idx ] ].x - this->nodes[ cell.cellToNode[ ( idx - 1 ) % 4 ] ].x;
+    //        v1.y =   this->nodes[ cell.cellToNode[ idx ] ].y - this->nodes[ cell.cellToNode[ ( idx - 1 ) % 4 ] ].y;
+    //        v2.x = - this->nodes[ cell.cellToNode[ idx ] ].x + this->nodes[ cell.cellToNode[ ( idx + 1 ) % 4 ] ].x;
+    //        v2.y = - this->nodes[ cell.cellToNode[ idx ] ].y + this->nodes[ cell.cellToNode[ ( idx + 1 ) % 4 ] ].y;
+
+    //        double v1Length = sqrt( v1.x*v1.x + v1.y*v1.y );
+    //        double v2Length = sqrt( v2.x*v2.x + v2.y*v2.y );
+
+    //        double v1DotV2  = v1.x*v2.x + v1.y*v2.y;
+
+    //        bool isConcave = v1.x*v2.y - v1.y*v2.x < 0.0;
+
+    //        double argument = v1DotV2 / ( v1Length * v2Length );
+
+    //        bool isCollinear = false;
+    //        
+    //        // the acos function does not like the argument 1.0, hence the special treatment
+    //        if( fabs( v1DotV2 / ( v1Length * v2Length ) - 1.0 ) < 1.0e-10 )
+    //            isCollinear = true;
+    //        else
+    //            isCollinear = acos( v1DotV2 / ( v1Length * v2Length ) ) < M_PI / 4.0;
+
+    //        //////////////////////////////////////////////////////////////////////////
+
+    //        uint neighborIdx1 = cell.cellToCell[   idx           ];
+    //        uint neighborIdx2 = cell.cellToCell[ ( idx + 1 ) % 4 ];
+
+    //        bool neighborCellsExist = ( ( neighborIdx1 != INVALID_IDX && this->cells[ neighborIdx1 ].type != STOPPER_SOLID ) ||
+    //                                    ( neighborIdx2 != INVALID_IDX && this->cells[ neighborIdx2 ].type != STOPPER_SOLID ) );
+
+    //        //////////////////////////////////////////////////////////////////////////
+
+    //        if( isConcave || isCollinear ){
+    //            if( !neighborCellsExist ){
+    //                cellToNodeTMP[idx] = INVALID_IDX;
+    //            }
+    //            else{
+    //                nodes[ cell.cellToNode[ idx ] ].x -= this->displacement[ cell.cellToNode[ idx ] ].x / double( this->nDisplacements[ cell.cellToNode[ idx ] ] );
+    //                nodes[ cell.cellToNode[ idx ] ].y -= this->displacement[ cell.cellToNode[ idx ] ].y / double( this->nDisplacements[ cell.cellToNode[ idx ] ] );
+    //            }
+    //        }
+    //    }
+
+    //    cell.cellToNode = cellToNodeTMP;
+    //}
+}
+
+void GksMeshAdapter::computeCellGeometry()
+{    
+    for( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
+        
+        MeshCell& cell = this->cells[ cellIdx ];
+
+        Vec3 cellCenter;
+
+        for( uint node = 0; node < 8; node++ ){
+            cellCenter = cellCenter + this->nodes[ cell.cellToNode[node] ];
+        }
+
+        cell.cellCenter.x = cellCenter.x / eight;
+        cell.cellCenter.y = cellCenter.y / eight;
+        cell.cellCenter.z = cellCenter.z / eight;
+
+    //    MeshCell& cell = this->cells[ cellIdx ];
+
+    //    uint nNodes = 0;
+    //    for( uint idx : cell.cellToNode ) if( idx != INVALID_IDX ) nNodes++;
+
+    //    if( nNodes == 3 ){
+    //    
+    //        arraytypes::uint3 cellToNode;
+    //        for( uint idx = 0, counter = 0; idx < 4; idx++ )
+    //            if( cell.cellToNode[idx] != INVALID_IDX ) 
+    //                cellToNode[counter++] = cell.cellToNode[idx];
+    //    
+    //        cell.cellCenter.x = ( this->nodes[ cellToNode[0] ].x
+    //                            + this->nodes[ cellToNode[1] ].x
+    //                            + this->nodes[ cellToNode[2] ].x ) / 3.0;
+    //        cell.cellCenter.y = ( this->nodes[ cellToNode[0] ].y
+    //                            + this->nodes[ cellToNode[1] ].y
+    //                            + this->nodes[ cellToNode[2] ].y ) / 3.0;
+
+    //        cell.cellVolume = 0.5 * ( this->nodes[ cellToNode[0] ].x * ( this->nodes[ cellToNode[1] ].y - this->nodes[ cellToNode[2] ].y )
+    //                                + this->nodes[ cellToNode[1] ].x * ( this->nodes[ cellToNode[2] ].y - this->nodes[ cellToNode[0] ].y )
+    //                                + this->nodes[ cellToNode[2] ].x * ( this->nodes[ cellToNode[0] ].y - this->nodes[ cellToNode[1] ].y ) );
+
+    //    }
+    //    else if( nNodes == 4 ){
+    //        
+    //        arraytypes::Vec2 triCenter[2];
+    //        triCenter[0].x =  (this->nodes[ cell.cellToNode[0] ].x + this->nodes[ cell.cellToNode[1] ].x +                                       this->nodes[ cell.cellToNode[3] ].x) / 3.0;
+    //        triCenter[0].y =  (this->nodes[ cell.cellToNode[0] ].y + this->nodes[ cell.cellToNode[1] ].y +                                       this->nodes[ cell.cellToNode[3] ].y) / 3.0;
+    //        triCenter[1].y =  (                                      this->nodes[ cell.cellToNode[1] ].y + this->nodes[ cell.cellToNode[2] ].y + this->nodes[ cell.cellToNode[3] ].y) / 3.0;
+    //        triCenter[1].x =  (                                      this->nodes[ cell.cellToNode[1] ].x + this->nodes[ cell.cellToNode[2] ].x + this->nodes[ cell.cellToNode[3] ].x) / 3.0;
+
+    //        double triVolume[2];
+    //        triVolume[0] = 0.5 * fabs( this->nodes[ cell.cellToNode[0] ].x * ( this->nodes[ cell.cellToNode[1] ].y - this->nodes[ cell.cellToNode[3] ].y )
+    //                                 + this->nodes[ cell.cellToNode[1] ].x * ( this->nodes[ cell.cellToNode[3] ].y - this->nodes[ cell.cellToNode[0] ].y )
+    //                                 + this->nodes[ cell.cellToNode[3] ].x * ( this->nodes[ cell.cellToNode[0] ].y - this->nodes[ cell.cellToNode[1] ].y ) );
+    //        triVolume[1] = 0.5 * fabs( this->nodes[ cell.cellToNode[2] ].x * ( this->nodes[ cell.cellToNode[3] ].y - this->nodes[ cell.cellToNode[1] ].y )
+    //                                 + this->nodes[ cell.cellToNode[3] ].x * ( this->nodes[ cell.cellToNode[1] ].y - this->nodes[ cell.cellToNode[2] ].y )
+    //                                 + this->nodes[ cell.cellToNode[1] ].x * ( this->nodes[ cell.cellToNode[2] ].y - this->nodes[ cell.cellToNode[3] ].y ) );
+
+    //        cell.cellVolume   = triVolume[0] + triVolume[1];
+    //        cell.cellCenter.x = ( triCenter[0].x * triVolume[0] + triCenter[1].x * triVolume[1] ) / cell.cellVolume;
+    //        cell.cellCenter.y = ( triCenter[0].y * triVolume[0] + triCenter[1].y * triVolume[1] ) / cell.cellVolume;
+    //    }
+    }
+}
+
+void GksMeshAdapter::generateSolidGhostCells()
+{
+    //std::vector<MeshCell> newCells;
+
+    //for( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
+
+    //    MeshCell& cell = this->cells[ cellIdx ];
+
+    //    if( cell.type != BC_SOLID ) continue;
+    //    
+    //    for( uint idx = 0; idx < 4; idx++ ){
+    //        
+    //        if( cell.cellToCell[ idx ] == INVALID_IDX ){
+    //            
+    //            cell.cellToCell[ idx ] = this->cells.size() + newCells.size();
+
+    //            if( cell.cellToNode[ idx ] == INVALID_IDX )
+    //                cell.cellToCell[ ( idx + 1 ) % 4 ] = this->cells.size() + newCells.size();
+
+    //            if( cell.cellToNode[ ( idx - 1 ) % 4 ] == INVALID_IDX )
+    //                cell.cellToCell[ ( idx - 1 ) % 4 ] = this->cells.size() + newCells.size();
+
+    //            uint neighborIdx = cell.cellToCell[ ( idx + 1 ) % 4 ];
+    //            if( neighborIdx != INVALID_IDX && neighborIdx < this->cells.size() )
+    //                this->cells[ neighborIdx ].cellToCell[ 4 + ( idx - 1 ) % 4 ] = this->cells.size() + newCells.size();
+
+    //            neighborIdx = cell.cellToCell[ ( idx - 1 ) % 4 ];
+    //            if( neighborIdx != INVALID_IDX && neighborIdx < this->cells.size() )
+    //                this->cells[ neighborIdx ].cellToCell[ 4 + ( idx + 0 ) % 4 ] = this->cells.size() + newCells.size();
+
+    //            newCells.push_back( MeshCell() );
+    //            
+    //            newCells.back().isGhostCell = true;
+    //            newCells.back().type        = STOPPER_SOLID;
+    //            newCells.back().level       = cell.level;
+    //        }
+    //    }
+    //}
+
+    //this->cells.insert( this->cells.end(), newCells.begin(), newCells.end() );
+}
+
+void GksMeshAdapter::computeGhostCellGeometry()
+{
+    //for( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
+
+    //    MeshCell& cell = this->cells[ cellIdx ];
+
+    //    if( cell.type != BC_SOLID ) continue;
+
+    //    for( uint idx = 0; idx < 4; idx++ ){
+    //        
+    //        MeshCell& neighborCell = this->cells[ cell.cellToCell[ idx ] ];
+
+    //        if( neighborCell.type != STOPPER_SOLID ) continue;
+    //    
+    //        arraytypes::Vec2 faceCenter;
+
+    //        uint node0 = cell.cellToNode[ ( idx - 1 ) % 4 ];
+    //        uint node1 = cell.cellToNode[   idx           ];
+
+    //        if( node0 == INVALID_IDX ) continue;
+
+    //        if( node1 == INVALID_IDX ) node1 = cell.cellToNode[ ( idx + 1 ) % 4 ];
+
+    //        faceCenter.x = 0.5 * ( this->nodes[ node0 ].x + this->nodes[ node1 ].x );
+    //        faceCenter.y = 0.5 * ( this->nodes[ node0 ].y + this->nodes[ node1 ].y );
+
+    //        arraytypes::Vec2 newNode;
+
+    //        //newNode.x = 2.0 * faceCenter.x - cell.cellCenter.x;
+    //        //newNode.y = 2.0 * faceCenter.y - cell.cellCenter.y;
+
+    //        //////////////////////////////////////////////////////////////////////////
+
+    //        arraytypes::Vec2 v01 ( this->nodes[ node1 ].x - this->nodes[ node0 ].x,
+    //                               this->nodes[ node1 ].y - this->nodes[ node0 ].y );
+
+    //        arraytypes::Vec2 vD0 ( this->nodes[ node0 ].x - cell.cellCenter.x,
+    //                               this->nodes[ node0 ].y - cell.cellCenter.y );
+
+    //        double alpha = - ( vD0.x * v01.x + vD0.y * v01.y ) / ( v01.x * v01.x + v01.y * v01.y );
+
+    //        arraytypes::Vec2 vDP( this->nodes[ node0 ].x + alpha * v01.x - cell.cellCenter.x,
+    //                              this->nodes[ node0 ].y + alpha * v01.y - cell.cellCenter.y );
+
+    //        newNode.x = cell.cellCenter.x + 2.0 * vDP.x;
+    //        newNode.y = cell.cellCenter.y + 2.0 * vDP.y;
+
+    //        //////////////////////////////////////////////////////////////////////////
+
+    //        neighborCell.cellCenter = newNode;
+    //        
+    //        neighborCell.cellToNode[0] = node1;
+    //        neighborCell.cellToNode[1] = node0;
+    //        neighborCell.cellToNode[2] = this->nodes.size();
+
+    //        // dummy value to identify it as ghost cell
+    //        neighborCell.cellVolume = -1.0;
+
+    //        this->nodes.push_back( newNode );
+    //    }
+    //}
+}
+
+void GksMeshAdapter::generateFaces(SPtr<MultipleGridBuilder> gridBuilder)
+{
+    std::vector< SPtr<Grid> > grids = gridBuilder->getGrids();
+
+    this->faces.reserve( 2 * this->cells.size() );
+
+    for( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
+    
+        MeshCell& cell = this->cells[ cellIdx ];
+
+        if( cell.type == BC_SOLID || cell.type == STOPPER_SOLID ) continue;
+
+        // generate faces in positive direction
+        for( uint neighborIdx = 0; neighborIdx < 6; neighborIdx += 2 ){
+
+            if( cell.faceExists[ neighborIdx ] ) continue;
+
+            if( cell.cellToCell[ neighborIdx ] == INVALID_INDEX ) continue;
+
+            uint neighborCellIdx = cell.cellToCell[ neighborIdx ];
+
+            MeshCell& neighborCell = this->cells[ neighborCellIdx ];
+
+            if( cell.isGhostCell && neighborCell.isGhostCell ) continue;
+
+            if( cell.isCoarseGhostCell() || neighborCell.isCoarseGhostCell() ) continue;
+
+            //////////////////////////////////////////////////////////////////////////
+
+            MeshFace newFace;
+
+            newFace.level = cell.level;
+
+            if( neighborIdx == 0 )
+            {
+                newFace.faceToNode[ 0 ] = cell.cellToNode[ 3 ];
+                newFace.faceToNode[ 1 ] = cell.cellToNode[ 1 ];
+                newFace.faceToNode[ 2 ] = cell.cellToNode[ 0 ];
+                newFace.faceToNode[ 3 ] = cell.cellToNode[ 2 ];
+                newFace.orientation = 'x';
+            }
+            if( neighborIdx == 2 )
+            {
+                newFace.faceToNode[ 0 ] = cell.cellToNode[ 5 ];
+                newFace.faceToNode[ 1 ] = cell.cellToNode[ 4 ];
+                newFace.faceToNode[ 2 ] = cell.cellToNode[ 0 ];
+                newFace.faceToNode[ 3 ] = cell.cellToNode[ 1 ];
+                newFace.orientation = 'y';
+            }
+            if( neighborIdx == 4 )
+            {
+                newFace.faceToNode[ 0 ] = cell.cellToNode[ 6 ];
+                newFace.faceToNode[ 1 ] = cell.cellToNode[ 2 ];
+                newFace.faceToNode[ 2 ] = cell.cellToNode[ 0 ];
+                newFace.faceToNode[ 3 ] = cell.cellToNode[ 4 ];
+                newFace.orientation = 'z';
+            }
+
+            //////////////////////////////////////////////////////////////////////////
+
+            cell.faceExists[ neighborIdx ] = true;
+
+            // register face at neighbor
+            for( uint idx = 0; idx < 6; idx++ ){
+                if( neighborCell.cellToCell[ idx ] == cellIdx ){
+                    neighborCell.faceExists[ idx ] = true;
+                    break;
+                }
+            }
+
+            //////////////////////////////////////////////////////////////////////////
+
+            newFace.negCell = cellIdx;
+            newFace.posCell = neighborCellIdx;
+
+            //////////////////////////////////////////////////////////////////////////
+
+            if ( cell.type == FLUID_CFF && neighborCell.type == FLUID_FCF ) newFace.negCellCoarse = cell.parent;
+            if ( cell.type == FLUID_FCF && neighborCell.type == FLUID_CFF ) newFace.posCellCoarse = neighborCell.parent;
+
+            //////////////////////////////////////////////////////////////////////////
+            
+            Vec3 faceCenter;
+
+            for( uint node = 0; node < 4; node++ ){
+                faceCenter = faceCenter + this->nodes[ newFace.faceToNode[node] ];
+            }
+
+            newFace.faceCenter.x = faceCenter.x / four;
+            newFace.faceCenter.y = faceCenter.y / four;
+            newFace.faceCenter.z = faceCenter.z / four;
+
+            this->faces.push_back( newFace );
+        }
+    }
+}
+
+void GksMeshAdapter::generateSolidFaces(SPtr<MultipleGridBuilder> gridBuilder)
+{
+
+    //std::vector< SPtr<Grid> > grids = gridBuilder->getGrids();
+
+    //this->faces.reserve( 2 * this->cells.size() );
+
+    //for( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
+    //
+    //    MeshCell& cell = this->cells[ cellIdx ];
+
+    //    if( ! ( cell.type == BC_SOLID ) ) continue;
+
+    //    for( uint neighborIdx = 0; neighborIdx < 4; neighborIdx++ ){
+
+    //        if( cell.faceExists[ neighborIdx ] ) continue;
+
+    //        if( cell.cellToCell[ neighborIdx ] == INVALID_IDX ) continue;
+
+    //        uint neighborCellIdx = cell.cellToCell[ neighborIdx ];
+
+    //        MeshCell& neighborCell = this->cells[ neighborCellIdx ];
+
+    //        if( cell.isGhostCell && neighborCell.isGhostCell ) continue;
+
+    //        if( cell.isCoarseGhostCell() || neighborCell.isCoarseGhostCell() ) continue;
+
+    //        //////////////////////////////////////////////////////////////////////////
+
+    //        MeshFace newFace;
+
+    //        newFace.level = cell.level;
+
+    //        uint node0 = cell.cellToNode[ ( neighborIdx - 1 ) % 4 ];
+    //        uint node1 = cell.cellToNode[   neighborIdx           ];
+
+    //        if( node0 == INVALID_IDX ) continue;
+
+    //        if( node1 == INVALID_IDX ) node1 = cell.cellToNode[ ( neighborIdx + 1 ) % 4 ];
+
+    //        newFace.faceToNode[ 0 ] = node0;
+    //        newFace.faceToNode[ 1 ] = node1;
+
+    //        //////////////////////////////////////////////////////////////////////////
+
+    //        newFace.orientation = 'a';
+
+    //        //////////////////////////////////////////////////////////////////////////
+
+    //        cell.faceExists[ neighborIdx ] = true;
+
+    //        // register face at neighbor
+    //        for( uint idx = 0; idx < 4; idx++ ){
+    //            if( neighborCell.cellToCell[ idx ] == cellIdx ){
+    //                neighborCell.faceExists[ idx ] = true;
+    //                break;
+    //            }
+    //        }
+
+    //        //////////////////////////////////////////////////////////////////////////
+
+    //        newFace.faceToCell[ 0 ] = cellIdx;
+    //        newFace.faceToCell[ 1 ] = neighborCellIdx;
+    //        
+    //        //////////////////////////////////////////////////////////////////////////
+    //        //////////////////////////////////////////////////////////////////////////
+
+    //        if( false )
+    //        {
+    //            if (neighborCell.type != STOPPER_SOLID) {
+    //                newFace.faceToCell[2] = cell.cellToCell[(neighborIdx + 1) % 4];
+    //                newFace.faceToCell[3] = cell.cellToCell[(neighborIdx - 1) % 4];
+
+    //                newFace.faceToCell[4] = cell.cellToCell[neighborIdx + 4];
+    //                newFace.faceToCell[5] = cell.cellToCell[neighborIdx + 3];
+    //            }
+    //            else {
+    //                newFace.faceToCell[2] = cell.cellToCell[(neighborIdx + 1) % 4];
+    //                newFace.faceToCell[3] = cell.cellToCell[(neighborIdx - 1) % 4];
+
+    //                if (newFace.faceToCell[2] == newFace.faceToCell[1])
+    //                    newFace.faceToCell[2] = cell.cellToCell[(neighborIdx + 2) % 4];
+
+    //                if (newFace.faceToCell[3] == newFace.faceToCell[1])
+    //                    newFace.faceToCell[3] = cell.cellToCell[(neighborIdx - 2) % 4];
+    //            }
+
+    //        }
+    //        //////////////////////////////////////////////////////////////////////////
+
+    //        if( true )
+    //        {
+    //            // search for suitable cells
+
+    //            std::vector<uint> candidates;
+
+    //            std::function<void(uint)> findCandidates = [&](uint candidateIdx)
+    //            {
+    //                MeshCell candidateCell = this->cells[candidateIdx];
+
+    //                bool sharesNode = false;
+
+    //                for (auto faceNodeIdx : newFace.faceToNode)
+    //                    for (auto candidateNodeIdx : candidateCell.cellToNode)
+    //                        if (faceNodeIdx == candidateNodeIdx)
+    //                            sharesNode = true;
+
+    //                if (!sharesNode) return;
+
+    //                candidates.push_back(candidateIdx);
+
+    //                for (auto candidateCellIdx : candidateCell.cellToCell)
+    //                    if (candidateCellIdx != INVALID_IDX)
+    //                        if (std::find(candidates.begin(), candidates.end(), candidateCellIdx) == candidates.end())
+    //                            findCandidates(candidateCellIdx);
+    //            };
+
+    //            findCandidates(cellIdx);
+
+    //            // https://stackoverflow.com/questions/3385229/c-erase-vector-element-by-value-rather-than-by-position
+    //            candidates.erase(std::remove(candidates.begin(), candidates.end(), cellIdx), candidates.end());
+    //            candidates.erase(std::remove(candidates.begin(), candidates.end(), neighborCellIdx), candidates.end());
+
+    //            //////////////////////////////////////////////////////////////////////////
+
+    //            newFace.faceCenter.x = 0.5 * (this->nodes[newFace.faceToNode[1]].x + this->nodes[newFace.faceToNode[0]].x);
+    //            newFace.faceCenter.y = 0.5 * (this->nodes[newFace.faceToNode[1]].y + this->nodes[newFace.faceToNode[0]].y);
+
+    //            // choose cells
+
+    //            if (candidates.size() <= 4) {
+
+    //                uint j = 2;
+    //                for (uint i = 0; i < candidates.size(); i++) {
+    //                    newFace.faceToCell[j++] = candidates[i];
+    //                }
+    //                while (j < 6) {
+    //                    newFace.faceToCell[j++] = INVALID_IDX;
+    //                }
+    //            }
+    //            else
+    //            {
+    //                uint numberOfPermutations = pow(candidates.size(), (candidates.size() - 4));
+
+    //                uint   minimalPermutation = INVALID_IDX;
+    //                double minimalDeviation = 1.0e99;
+
+    //                for (uint permutation = 0; permutation < numberOfPermutations; permutation++)
+    //                {
+    //                    std::vector<uint> jumpList;
+    //                    uint tmp = permutation;
+    //                    do
+    //                    {
+    //                        jumpList.push_back(tmp % candidates.size());
+    //                        tmp = tmp / candidates.size();
+    //                    } while (tmp > 0);
+
+    //                    std::sort(jumpList.begin(), jumpList.end());
+    //                    jumpList.erase(std::unique(jumpList.begin(), jumpList.end()), jumpList.end());
+
+    //                    if (jumpList.size() != (candidates.size() - 4)) continue;
+
+    //                    arraytypes::Vec2 centroid;
+
+    //                    centroid.x += 1.0 / 6.0 * cell.cellCenter.x;
+    //                    centroid.y += 1.0 / 6.0 * cell.cellCenter.y;
+    //                    centroid.x += 1.0 / 6.0 * neighborCell.cellCenter.x;
+    //                    centroid.y += 1.0 / 6.0 * neighborCell.cellCenter.y;
+
+    //                    for (uint i = 0; i < candidates.size(); i++)
+    //                    {
+    //                        if (std::find(jumpList.begin(), jumpList.end(), i) == jumpList.end())
+    //                        {
+    //                            centroid.x += 1.0 / 6.0 * this->cells[candidates[i]].cellCenter.x;
+    //                            centroid.y += 1.0 / 6.0 * this->cells[candidates[i]].cellCenter.y;
+    //                        }
+    //                    }
+
+    //                    double deviation = sqrt((newFace.faceCenter.x - centroid.x)
+    //                        * (newFace.faceCenter.x - centroid.x)
+    //                        + (newFace.faceCenter.y - centroid.y)
+    //                        * (newFace.faceCenter.y - centroid.y));
+
+    //                    if (deviation < minimalDeviation)
+    //                    {
+    //                        minimalPermutation = permutation;
+    //                        minimalDeviation = deviation;
+    //                    }
+    //                }
+
+    //                std::vector<uint> jumpList;
+    //                uint tmp = minimalPermutation;
+    //                do
+    //                {
+    //                    jumpList.push_back(tmp % candidates.size());
+    //                    tmp = tmp / candidates.size();
+    //                } while (tmp > 0);
+
+    //                uint j = 2;
+    //                for (uint i = 0; i < candidates.size(); i++)
+    //                {
+    //                    if (std::find(jumpList.begin(), jumpList.end(), i) == jumpList.end())
+    //                    {
+    //                        newFace.faceToCell[j++] = candidates[i];
+    //                    }
+    //                }
+    //            }
+    //        }
+
+    //        //////////////////////////////////////////////////////////////////////////
+
+    //        newFace.negCell = cellIdx;
+    //        newFace.posCell = neighborCellIdx;
+
+    //        //////////////////////////////////////////////////////////////////////////
+
+    //        if ( cell.type == FLUID_CFF && neighborCell.type == FLUID_FCF ) newFace.negCell = cell.parent;
+    //        if ( cell.type == FLUID_FCF && neighborCell.type == FLUID_CFF ) newFace.posCell = neighborCell.parent;
+
+    //        //////////////////////////////////////////////////////////////////////////
+
+    //        arraytypes::Vec2 faceVec( this->nodes[ newFace.faceToNode[ 1 ] ].x - this->nodes[ newFace.faceToNode[ 0 ] ].x,
+    //                                  this->nodes[ newFace.faceToNode[ 1 ] ].y - this->nodes[ newFace.faceToNode[ 0 ] ].y );
+
+    //        newFace.faceArea = sqrt( faceVec.x * faceVec.x + faceVec.y * faceVec.y );
+
+    //        newFace.faceCenter.x = 0.5 * ( this->nodes[ newFace.faceToNode[ 1 ] ].x + this->nodes[ newFace.faceToNode[ 0 ] ].x );
+    //        newFace.faceCenter.y = 0.5 * ( this->nodes[ newFace.faceToNode[ 1 ] ].y + this->nodes[ newFace.faceToNode[ 0 ] ].y );
+
+    //        newFace.faceNormal.x =   faceVec.y / newFace.faceArea;
+    //        newFace.faceNormal.y = - faceVec.x / newFace.faceArea;
+
+    //        //////////////////////////////////////////////////////////////////////////
+
+    //        this->faces.push_back( newFace );
+    //    }
+    //}
+}
+
+void GksMeshAdapter::sortFaces()
+{
+    real xMax = ( *std::max_element( this->faces.begin(), this->faces.end(), [this]( MeshFace lhs, MeshFace rhs ){ return lhs.faceCenter.x < rhs.faceCenter.x; } ) ).faceCenter.x;
+    real yMax = ( *std::max_element( this->faces.begin(), this->faces.end(), [this]( MeshFace lhs, MeshFace rhs ){ return lhs.faceCenter.y < rhs.faceCenter.y; } ) ).faceCenter.y;
+    real zMax = ( *std::max_element( this->faces.begin(), this->faces.end(), [this]( MeshFace lhs, MeshFace rhs ){ return lhs.faceCenter.z < rhs.faceCenter.z; } ) ).faceCenter.z;
+    
+    real xMin = ( *std::min_element( this->faces.begin(), this->faces.end(), [this]( MeshFace lhs, MeshFace rhs ){ return lhs.faceCenter.x < rhs.faceCenter.x; } ) ).faceCenter.x;
+    real yMin = ( *std::min_element( this->faces.begin(), this->faces.end(), [this]( MeshFace lhs, MeshFace rhs ){ return lhs.faceCenter.y < rhs.faceCenter.y; } ) ).faceCenter.y;
+    real zMin = ( *std::min_element( this->faces.begin(), this->faces.end(), [this]( MeshFace lhs, MeshFace rhs ){ return lhs.faceCenter.z < rhs.faceCenter.z; } ) ).faceCenter.z;
+
+    real xRange = xMax - xMin;
+    real yRange = yMax - yMin;
+    real zRange = zMax - zMin;
+
+    std::sort(  this->faces.begin(), this->faces.end(),
+                [&,this]( MeshFace lhs, MeshFace rhs ){
+
+                    if( lhs.level != rhs.level ) return lhs.level < rhs.level;
+
+                    if( lhs.orientation != rhs.orientation ){
+                        if      ( lhs.orientation == 'x' && rhs.orientation == 'y' ) return true;
+                        else if ( lhs.orientation == 'y' && rhs.orientation == 'z' ) return true;
+                        else if ( lhs.orientation == 'x' && rhs.orientation == 'z' ) return true;
+                        else                                                         return false;
+                    }
+
+                    return ( ten * ten * lhs.faceCenter.z / zRange + ten * lhs.faceCenter.y / yRange + lhs.faceCenter.x / xRange ) < 
+                           ( ten * ten * rhs.faceCenter.z / zRange + ten * rhs.faceCenter.y / yRange + rhs.faceCenter.x / xRange );
+                }
+             );
+}
+
+void GksMeshAdapter::countFaces()
+{
+    this->numberOfFacesPerLevelXYZ.resize( 3 * this->numberOfLevels );
+    this->startOfFacesPerLevelXYZ.resize ( 3 * this->numberOfLevels );
+
+    for( auto& i : this->numberOfFacesPerLevelXYZ ) i = 0;
+    for( auto& i : this->startOfFacesPerLevelXYZ  ) i = 0;
+
+    for( auto& face : this->faces ){
+        if      ( face.orientation == 'x' ) this->numberOfFacesPerLevelXYZ[ 3 * face.level     ]++;
+        else if ( face.orientation == 'y' ) this->numberOfFacesPerLevelXYZ[ 3 * face.level + 1 ]++;
+        else if ( face.orientation == 'z' ) this->numberOfFacesPerLevelXYZ[ 3 * face.level + 2 ]++;
+    }
+
+    this->startOfFacesPerLevelXYZ[0] = 0;
+
+    for( uint level = 1; level < 3 * this->numberOfLevels; level++ ){
+        
+        this->startOfFacesPerLevelXYZ[level] = this->startOfFacesPerLevelXYZ [level - 1]
+                                             + this->numberOfFacesPerLevelXYZ[level - 1];
+    }
+}
+
+void GksMeshAdapter::findSolidFaces()
+{
+    //for( uint faceIdx = 0; faceIdx < this->faces.size(); faceIdx++ ){
+
+    //    MeshFace& face = this->faces[ faceIdx ];
+
+    //    if( this->cells[ face.posCell ].type == STOPPER_SOLID )
+    //        this->solidFaces.push_back( faceIdx );
+    //}
+}
+
+void GksMeshAdapter::generateInterfaceConnectivity()
+{
+    this->numberOfFineToCoarsePerLevel.resize( this->numberOfLevels );
+    this->startOfFineToCoarsePerLevel.resize ( this->numberOfLevels );
+    this->numberOfCoarseToFinePerLevel.resize( this->numberOfLevels );
+    this->startOfCoarseToFinePerLevel.resize ( this->numberOfLevels );
+
+    for( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
+
+        MeshCell& cell = this->cells[ cellIdx ];
+
+        if( cell.type == FLUID_FCC ){
+
+            uint_9 connectivity;
+
+            connectivity[ 0 ] = cellIdx;
+            connectivity[ 1 ] = cell.children[ 0 ];
+            connectivity[ 2 ] = cell.children[ 1 ];
+            connectivity[ 3 ] = cell.children[ 2 ];
+            connectivity[ 4 ] = cell.children[ 3 ];
+            connectivity[ 5 ] = cell.children[ 4 ];
+            connectivity[ 6 ] = cell.children[ 5 ];
+            connectivity[ 7 ] = cell.children[ 6 ];
+            connectivity[ 8 ] = cell.children[ 7 ];
+
+            this->fineToCoarse.push_back( connectivity );
+
+            this->numberOfFineToCoarsePerLevel[ cell.level ]++;
+        }
+
+        if( cell.type == FLUID_CFC ){
+            
+            uint_15 connectivity;
+
+            connectivity[  0 ] = cellIdx;
+
+            connectivity[  1 ] = cell.cellToCell[ 0 ];
+            connectivity[  2 ] = cell.cellToCell[ 1 ];
+            connectivity[  3 ] = cell.cellToCell[ 2 ];
+            connectivity[  4 ] = cell.cellToCell[ 3 ];
+            connectivity[  5 ] = cell.cellToCell[ 4 ];
+            connectivity[  6 ] = cell.cellToCell[ 5 ];
+
+            connectivity[  7 ] = cell.children[ 0 ];
+            connectivity[  8 ] = cell.children[ 1 ];
+            connectivity[  9 ] = cell.children[ 2 ];
+            connectivity[ 10 ] = cell.children[ 3 ];
+            connectivity[ 11 ] = cell.children[ 4 ];
+            connectivity[ 12 ] = cell.children[ 5 ];
+            connectivity[ 13 ] = cell.children[ 6 ];
+            connectivity[ 14 ] = cell.children[ 7 ];
+
+            this->coarseToFine.push_back( connectivity );
+
+            numberOfCoarseToFinePerLevel[ cell.level ]++;
+        }
+    }
+
+        std::cout << numberOfCoarseToFinePerLevel[ 0 ] << " " << this->numberOfFineToCoarsePerLevel[ 0 ] << std::endl;
+    
+    this->startOfFineToCoarsePerLevel[0] = 0;
+    this->startOfCoarseToFinePerLevel[0] = 0;
+
+    for( uint level = 1; level < this->numberOfLevels; level++ ){
+        
+        this->startOfFineToCoarsePerLevel[level] = this->startOfFineToCoarsePerLevel [level - 1]
+                                                 + this->numberOfFineToCoarsePerLevel[level - 1];
+        
+        this->startOfCoarseToFinePerLevel[level] = this->startOfCoarseToFinePerLevel [level - 1]
+                                                 + this->numberOfCoarseToFinePerLevel[level - 1];
+    }
+}
+
+void GksMeshAdapter::writeMeshVTK(std::string filename)
+{
+    *logging::out << logging::Logger::INFO_INTERMEDIATE << "writeMeshVTK( " << filename << " )" << "\n";
+
+    std::ofstream file;
+
+    file.open(filename);
+
+    file << "# vtk DataFile Version 3.0\n";
+    file << "by MeshGenerator\n";
+    file << "ASCII\n";
+    file << "DATASET UNSTRUCTURED_GRID\n";
+
+    file << "POINTS " << nodes.size() << " float" << std::endl;
+
+    for (auto node : nodes){
+        file << node.x << " " << node.y << " " << node.z << std::endl;
+    }
+
+    //////////////////////////////////////////////////////////////////////////
+
+    file << "CELLS " << this->cells.size() << " " << this->cells.size() * 9 << std::endl;
+
+    for ( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
+    
+        MeshCell& cell = this->cells[ cellIdx ];
+
+        uint_8 nodes;
+        for( auto& i : nodes ) i = INVALID_INDEX;
+
+        nodes[0] = cell.cellToNode[7];//[ 6 ];
+        nodes[1] = cell.cellToNode[3];//[ 5 ];
+        nodes[2] = cell.cellToNode[1];//[ 2 ];
+        nodes[3] = cell.cellToNode[5];//[ 1 ];
+        nodes[4] = cell.cellToNode[6];//[ 4 ];
+        nodes[5] = cell.cellToNode[2];//[ 7 ];
+        nodes[6] = cell.cellToNode[0];//[ 0 ];
+        nodes[7] = cell.cellToNode[4];//[ 3 ];
+
+        file << 8 << " ";
+
+        for( uint i = 0; i < 8; i++ ) file << nodes[i] << " ";
+
+        file << std::endl;
+    }
+
+    //////////////////////////////////////////////////////////////////////////
+
+    file << "CELL_TYPES " << this->cells.size() << std::endl;
+
+    for ( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
+        file << 12 << std::endl;
+    }
+    //////////////////////////////////////////////////////////////////////////
+
+    file << "\nCELL_DATA " << this->cells.size() << std::endl;
+
+    file << "FIELD Label " << 4 << std::endl;
+
+    //////////////////////////////////////////////////////////////////////////
+
+    file << "CellIdx 1 " << this->cells.size() << " int" << std::endl;
+
+    for ( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
+
+        file << cellIdx << std::endl;
+    }
+
+    //////////////////////////////////////////////////////////////////////////
+
+    file << "level 1 " << this->cells.size() << " int" << std::endl;
+
+    for ( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
+    
+        MeshCell& cell = this->cells[ cellIdx ];
+
+        file << cell.level << std::endl;
+    }
+
+    //////////////////////////////////////////////////////////////////////////
+
+    file << "type 1 " << this->cells.size() << " int" << std::endl;
+
+    for ( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
+    
+        MeshCell& cell = this->cells[ cellIdx ];
+
+        file << (uint) cell.type << std::endl;
+    }
+
+    //////////////////////////////////////////////////////////////////////////
+
+    file << "isGhostCell 1 " << this->cells.size() << " int" << std::endl;
+
+    for ( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
+    
+        MeshCell& cell = this->cells[ cellIdx ];
+
+        file << (uint) cell.isGhostCell << std::endl;
+    }
+
+    //////////////////////////////////////////////////////////////////////////
+
+    file.close();
+}
+
+void GksMeshAdapter::writeMeshFaceVTK(std::string filename)
+{
+    *logging::out << logging::Logger::INFO_INTERMEDIATE << "writeMeshFaceVTK( " << filename << " )" << "\n";
+
+    std::ofstream file;
+
+    file.open(filename);
+
+    file << "# vtk DataFile Version 3.0\n";
+    file << "by MeshGenerator\n";
+    file << "ASCII\n";
+    file << "DATASET UNSTRUCTURED_GRID\n";
+
+    file << "POINTS " << nodes.size() << " float" << std::endl;
+
+    for (auto node : nodes){
+        file << node.x << " " << node.y << " " << node.z << std::endl;
+    }
+
+    //////////////////////////////////////////////////////////////////////////
+
+    file << "CELLS " << this->faces.size() << " " << 5 * this->faces.size() << std::endl;
+
+    for ( uint faceIdx = 0; faceIdx < this->faces.size(); faceIdx++ ){
+
+        file << "4 ";
+
+        file << this->faces[ faceIdx ].faceToNode[0] << " ";
+        file << this->faces[ faceIdx ].faceToNode[1] << " ";
+        file << this->faces[ faceIdx ].faceToNode[2] << " ";
+        file << this->faces[ faceIdx ].faceToNode[3] << " ";
+
+        file << std::endl;
+    }
+
+    //////////////////////////////////////////////////////////////////////////
+
+    file << "CELL_TYPES " << this->faces.size() << std::endl;
+
+    for ( uint faceIdx = 0; faceIdx < this->faces.size(); faceIdx++ ){
+        file << "9" << std::endl;
+    }
+    //////////////////////////////////////////////////////////////////////////
+
+    file << "\nCELL_DATA " << this->faces.size() << std::endl;
+
+    file << "FIELD Label " << 3 << std::endl;
+
+    //////////////////////////////////////////////////////////////////////////
+
+    file << "FaceIdx 1 " << this->faces.size() << " int" << std::endl;
+
+    for ( uint faceIdx = 0; faceIdx < this->faces.size(); faceIdx++ ){
+
+        file << faceIdx << std::endl;
+    }
+
+    //////////////////////////////////////////////////////////////////////////
+
+    file << "level 1 " << this->faces.size() << " int" << std::endl;
+
+    for ( uint faceIdx = 0; faceIdx < this->faces.size(); faceIdx++ ){
+
+        file << this->faces[ faceIdx ].level << std::endl;
+    }
+
+    //////////////////////////////////////////////////////////////////////////
+
+    file << "orientation 1 " << this->faces.size() << " int" << std::endl;
+
+    for ( uint faceIdx = 0; faceIdx < this->faces.size(); faceIdx++ ){
+
+        file << (int)this->faces[ faceIdx ].orientation << std::endl;
+    }
+
+    //////////////////////////////////////////////////////////////////////////
+    //////////////////////////////////////////////////////////////////////////
+    //////////////////////////////////////////////////////////////////////////
+
+    file << "VECTORS posCell double" << std::endl;
+
+	for ( auto face : this->faces )
+    {
+        MeshCell& cell = this->cells[ face.posCell ];
+
+        Vec3 vec = cell.cellCenter - face.faceCenter;
+            
+		file << vec.x << " ";
+		file << vec.y << " ";
+		file << vec.z << std::endl;
+    }
+
+    file << "VECTORS negCell double" << std::endl;
+
+	for ( auto face : this->faces )
+    {
+        MeshCell& cell = this->cells[ face.negCell ];
+
+        Vec3 vec = cell.cellCenter - face.faceCenter;
+            
+		file << vec.x << " ";
+		file << vec.y << " ";
+		file << vec.z << std::endl;
+    }
+
+    //////////////////////////////////////////////////////////////////////////
+
+    file.close();
+}
+
+void GksMeshAdapter::writeMeshCellToCellVTK(std::string filename)
+{
+    //std::ofstream file;
+
+    //file.open(filename);
+
+    //file << "# vtk DataFile Version 3.0\n";
+    //file << "by MeshGenerator\n";
+    //file << "ASCII\n";
+    //file << "DATASET UNSTRUCTURED_GRID\n";
+
+    //file << "POINTS " << this->cells.size() << " float" << std::endl;
+
+    //for (auto cell : cells){
+    //    file << cell.cellCenter.x << " " << cell.cellCenter.y << " 0.0" << std::endl;
+    //}
+
+    ////////////////////////////////////////////////////////////////////////////
+
+    //file << "CELLS " << 8 * this->cells.size() << " " << 3 * 8 * this->cells.size() << std::endl;
+
+    //for ( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
+
+    //    for( uint i = 0; i < 8; i++ )
+    //        if(  this->cells[ cellIdx ].cellToCell[ i ] != INVALID_INDEX )
+    //            file << "2 " << cellIdx << " " << this->cells[ cellIdx ].cellToCell[ i ] << " " << std::endl;
+    //        else
+    //            file << "2 " << cellIdx << " " << cellIdx << " " << std::endl;
+    //}
+
+    ////////////////////////////////////////////////////////////////////////////
+
+    //file << "CELL_TYPES " << 8 * this->cells.size() << std::endl;
+
+    //for ( uint i = 0; i < 8 * this->cells.size(); i++ ){
+    //    file << "3" << std::endl;
+    //}
+    ////////////////////////////////////////////////////////////////////////////
+
+    //file << "\nCELL_DATA " << 8 * this->cells.size() << std::endl;
+
+    //file << "FIELD Label " << 2 << std::endl;
+
+    ////////////////////////////////////////////////////////////////////////////
+
+    //file << "CellIdx 1 " << 8 * this->cells.size() << " int" << std::endl;
+
+    //for ( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
+
+    //    for( uint i = 0; i < 8; i++ )
+    //        file << cellIdx << std::endl;
+    //}
+
+    ////////////////////////////////////////////////////////////////////////////
+
+    //file << "CellToCell 1 " << 8 * this->cells.size() << " int" << std::endl;
+
+    //for ( uint cellIdx = 0; cellIdx < this->cells.size(); cellIdx++ ){
+
+    //    for( uint i = 0; i < 8; i++ )
+    //        file << i << std::endl;
+    //}
+
+    ////////////////////////////////////////////////////////////////////////////
+
+    //file.close();
+}
+
+void GksMeshAdapter::writeMeshFaceToCellVTK(std::string filename)
+{
+    //std::ofstream file;
+
+    //file.open(filename);
+
+    //file << "# vtk DataFile Version 3.0\n";
+    //file << "by MeshGenerator\n";
+    //file << "ASCII\n";
+    //file << "DATASET UNSTRUCTURED_GRID\n";
+
+    //file << "POINTS " << this->cells.size() + this->faces.size() << " float" << std::endl;
+
+    //for (auto cell : cells){
+    //    file << cell.cellCenter.x << " " << cell.cellCenter.y << " 0.0" << std::endl;
+    //}
+
+    //for (auto face : faces){
+    //    file << face.faceCenter.x << " " << face.faceCenter.y << " 0.0" << std::endl;
+    //}
+
+    ////////////////////////////////////////////////////////////////////////////
+
+    //file << "CELLS " << 6 * this->faces.size() << " " << 3 * 6 * this->faces.size() << std::endl;
+
+    //for ( uint faceIdx = 0; faceIdx < this->faces.size(); faceIdx++ ){
+
+    //    for( uint i = 0; i < 6; i++ )
+    //        if(  this->faces[ faceIdx ].faceToCell[ i ] != INVALID_INDEX )
+    //            file << "2 " << this->cells.size() + faceIdx << " " << this->faces[ faceIdx ].faceToCell[ i ] << " " << std::endl;
+    //        else
+    //            file << "2 " << this->cells.size() + faceIdx << " " << this->cells.size() + faceIdx << " " << std::endl;
+    //}
+
+    ////////////////////////////////////////////////////////////////////////////
+
+    //file << "CELL_TYPES " << 6 * this->faces.size() << std::endl;
+
+    //for ( uint i = 0; i < 6 * this->faces.size(); i++ ){
+    //    file << "3" << std::endl;
+    //}
+    ////////////////////////////////////////////////////////////////////////////
+
+    //file << "\nCELL_DATA " << 6 * this->faces.size() << std::endl;
+
+    //file << "FIELD Label " << 2 << std::endl;
+
+    ////////////////////////////////////////////////////////////////////////////
+
+    //file << "FaceIdx 1 " << 6 * this->faces.size() << " int" << std::endl;
+
+    //for ( uint faceIdx = 0; faceIdx < this->faces.size(); faceIdx++ ){
+
+    //    for( uint i = 0; i < 6; i++ )
+    //        file << faceIdx << std::endl;
+    //}
+
+    ////////////////////////////////////////////////////////////////////////////
+
+    //file << "FaceToCell 1 " << 6 * this->faces.size() << " int" << std::endl;
+
+    //for ( uint faceIdx = 0; faceIdx < this->faces.size(); faceIdx++ ){
+
+    //    for( uint i = 0; i < 6; i++ )
+    //        file << i << std::endl;
+    //}
+
+    ////////////////////////////////////////////////////////////////////////////
+
+    //file.close();
+}
+
+double GksMeshAdapter::getDx(uint level)
+{
+    return dxCoarse / pow( 2.0, level );
+}
diff --git a/src/GksMeshAdapter/GksMeshAdapter.h b/src/GksMeshAdapter/GksMeshAdapter.h
new file mode 100644
index 000000000..ce53d4946
--- /dev/null
+++ b/src/GksMeshAdapter/GksMeshAdapter.h
@@ -0,0 +1,151 @@
+#ifndef GKS_MESH_ADAPTER_H
+#define GKS_MESH_ADAPTER_H
+
+#include <memory>
+#include <array>
+#include <vector>
+
+#include "Core/DataTypes.h"
+#include "Core/PointerDefinitions.h"
+
+#include "MeshCell.h"
+#include "MeshFace.h"
+
+
+class MultipleGridBuilder;
+
+class VF_PUBLIC GksMeshAdapter{
+
+public:
+
+    uint numberOfLevels;
+
+    double dxCoarse;
+
+    //////////////////////////////////////////////////////////////////////////
+
+    std::vector<Vec3> nodes;
+
+    //////////////////////////////////////////////////////////////////////////
+    //
+    //    C e l l    s o r t i n g :
+    //
+    //  | Level 0                   | Level 1                   | Level 2                   |
+    //  | FluidCells   | GhostCells | FluidCells   | GhostCells | FluidCells   | GhostCells | 
+    //
+    //  GhostCells: not included in Cell update, i.e. BoundaryCells and FCC-Cells
+    //  FluidCells: all other, including CFF-Cells
+    //
+    std::vector<MeshCell> cells;
+
+    std::vector<uint> numberOfCellsPerLevel;
+    std::vector<uint> numberOfBulkCellsPerLevel;
+    std::vector<uint> startOfCellsPerLevel;
+
+    //////////////////////////////////////////////////////////////////////////
+    //
+    //    F a c e    s o r t i n g :
+    //
+    //  | Level 0                              | Level 1                              | Level 2                              |
+    //  | x-normal   | y-normal   | z-normal   | x-normal   | y-normal   | z-normal   | x-normal   | y-normal   | z-normal   |
+    //
+    std::vector<MeshFace> faces;
+
+    std::vector<uint> numberOfFacesPerLevelXYZ;
+    std::vector<uint> startOfFacesPerLevelXYZ;
+
+    //std::vector<uint> solidFaces;
+
+    //////////////////////////////////////////////////////////////////////////
+    //
+    //    F i n e T o C o a r s e    s o r t i n g :
+    //
+    //  | Coarse Cell Idx | Child Idcs | ...
+    //
+    std::vector<uint_9> fineToCoarse;
+
+    std::vector<uint> numberOfFineToCoarsePerLevel;
+    std::vector<uint> startOfFineToCoarsePerLevel;
+
+    //////////////////////////////////////////////////////////////////////////
+    //
+    //    F i n e T o C o a r s e    s o r t i n g :
+    //
+    //  | Coarse Cell Idx | Coarse Neighbor Idcs | Child Idcs | ...
+    //
+    std::vector<uint_15> coarseToFine;
+
+    std::vector<uint> numberOfCoarseToFinePerLevel;
+    std::vector<uint> startOfCoarseToFinePerLevel;
+
+    //////////////////////////////////////////////////////////////////////////
+    // 
+    // Connectivity from LBM grid to GKS Mesh
+    //
+    //    cellIdx = gridToMesh[ level ][ gridIdx ]
+    //
+    std::vector< std::vector<uint> > gridToMesh;
+
+    //////////////////////////////////////////////////////////////////////////
+
+    uint_8 cornerCells;
+
+    //////////////////////////////////////////////////////////////////////////
+
+public:
+
+    void inputGrid( SPtr<MultipleGridBuilder> gridBuilder );
+
+    void findQuadtreeConnectivity( SPtr<MultipleGridBuilder> gridBuilder );
+
+    void findCellToCellConnectivity( SPtr<MultipleGridBuilder> gridBuilder );
+
+    void countCells();
+
+    void partitionCells();
+
+    void refreshCellConnectivity(const std::vector<uint>& idxMap);
+
+    void findCornerCells( SPtr<MultipleGridBuilder> gridBuilder, real z0 );
+
+    void generateNodes( SPtr<MultipleGridBuilder> gridBuilder );
+
+    void inputQs( SPtr<MultipleGridBuilder> gridBuilder );
+
+    void morphNodes();
+
+    void repairTriangularCells();
+
+    void computeCellGeometry();
+
+    void generateSolidGhostCells();
+
+    void computeGhostCellGeometry();
+
+    void generateFaces( SPtr<MultipleGridBuilder> gridBuilder );
+
+    void generateSolidFaces( SPtr<MultipleGridBuilder> gridBuilder );
+
+    void sortFaces();
+
+    void countFaces();
+
+    void findSolidFaces();
+
+    void generateInterfaceConnectivity();
+
+    void writeMeshVTK( std::string filename );
+
+    void writeMeshFaceVTK( std::string filename );
+
+    void writeMeshCellToCellVTK( std::string filename );
+
+    void writeMeshFaceToCellVTK( std::string filename );
+
+    //////////////////////////////////////////////////////////////////////////
+
+    double getDx(uint level);
+};
+
+
+#endif
\ No newline at end of file
diff --git a/src/GksMeshAdapter/MeshCell.cpp b/src/GksMeshAdapter/MeshCell.cpp
new file mode 100644
index 000000000..b63c87053
--- /dev/null
+++ b/src/GksMeshAdapter/MeshCell.cpp
@@ -0,0 +1,32 @@
+#include "MeshCell.h"
+
+#include "GridGenerator/grid/NodeValues.h"
+
+MeshCell::MeshCell(){
+
+    level   = INVALID_INDEX;
+    gridIdx = INVALID_INDEX;
+
+
+    for( uint& index : this->cellToNode     ) index = INVALID_INDEX;
+    for( uint& index : this->cellToEdgeNode ) index = INVALID_INDEX;
+    for( uint& index : this->cellToFaceNode ) index = INVALID_INDEX;
+    for( uint& index : this->cellToCell     ) index = INVALID_INDEX;
+    for( uint& index : this->children       ) index = INVALID_INDEX;
+    
+    parent = INVALID_INDEX;
+
+    for( bool& flag : this->faceExists    ) flag = false;
+
+    isGhostCell = false;
+}
+
+bool MeshCell::isCoarseGhostCell()
+{
+    return this->type == FLUID_FCC;
+}
+
+bool MeshCell::isFineGhostCell()
+{
+    return this->type == FLUID_CFF;
+}
diff --git a/src/GksMeshAdapter/MeshCell.h b/src/GksMeshAdapter/MeshCell.h
new file mode 100644
index 000000000..a0e6b0ec9
--- /dev/null
+++ b/src/GksMeshAdapter/MeshCell.h
@@ -0,0 +1,71 @@
+#ifndef MESH_CELL_H
+#define MESH_CELL_H
+
+#include <array>
+
+#include "Core/DataTypes.h"
+#include "Core/VectorTypes.h"
+#include "Core/ArrayTypes.h"
+
+struct VF_PUBLIC MeshCell{
+
+    uint level;
+    uint gridIdx;
+
+    //////////////////////////////////////////////////////////////////////////
+
+    uint_8 cellToNode;           uint_12 cellToEdgeNode;         uint_6 cellToFaceNode;
+
+    // for sorting see LBM f numbering
+    //                                   8                              
+    //     4 o--------o 0            o--------o                    o--------o 
+    //      /|       /|            7/|      4/|                   /|  4    /|  
+    //     / |      / |            /3| 11   / |                  / |    2 / |  
+    //  6 o--------o 2|           o--------o  |0                o--------o  |  
+    //    |  |     |  |           |  |  10 |  |                 |1 |     | 0|  
+    //    |5 o-----|--o 1        1|  o-----|--o                 |  o-----|--o  
+    //    | /      | /            |5/     2| /6                 | / 3    | /   
+    //    |/       |/             |/   9   |/                   |/    5  |/    
+    //  7 o--------o 3            o--------o                    o--------o      
+    //
+    //  z | / y
+    //    |/
+    //    +---- x
+    //     
+
+    //////////////////////////////////////////////////////////////////////////
+
+    uint_27 cellToCell;
+
+    // for sorting see LBM f numbering
+
+    //////////////////////////////////////////////////////////////////////////
+
+    uint_8 children;
+
+    // for sorting see cellToNode
+
+    uint  parent;
+
+    //////////////////////////////////////////////////////////////////////////
+
+    Vec3   cellCenter;
+
+    //////////////////////////////////////////////////////////////////////////
+
+    // order: +x, -x, +y, -y, +z, -z (see cellToCell)
+    bool_6 faceExists;
+
+    bool isGhostCell;
+
+    char type;
+
+    MeshCell();
+
+    bool isCoarseGhostCell();
+
+    bool isFineGhostCell();
+};
+
+
+#endif
\ No newline at end of file
diff --git a/src/GksMeshAdapter/MeshFace.cpp b/src/GksMeshAdapter/MeshFace.cpp
new file mode 100644
index 000000000..6ae2768a8
--- /dev/null
+++ b/src/GksMeshAdapter/MeshFace.cpp
@@ -0,0 +1,12 @@
+#include "MeshFace.h"
+
+MeshFace::MeshFace()
+{
+    for( uint& node : this->faceToNode ) node = INVALID_INDEX;
+
+    isWall = false;
+    posCell       = INVALID_INDEX;
+    negCell       = INVALID_INDEX;
+    posCellCoarse = INVALID_INDEX;
+    negCellCoarse = INVALID_INDEX;
+}
\ No newline at end of file
diff --git a/src/GksMeshAdapter/MeshFace.h b/src/GksMeshAdapter/MeshFace.h
new file mode 100644
index 000000000..a07f7f979
--- /dev/null
+++ b/src/GksMeshAdapter/MeshFace.h
@@ -0,0 +1,50 @@
+#ifndef MESH_FACE_H
+#define MESH_FACE_H
+
+#include "Core/DataTypes.h"
+#include "Core/VectorTypes.h"
+#include "Core/ArrayTypes.h"
+
+struct VF_PUBLIC MeshFace
+{
+    //////////////////////////////////////////////////////////////////////////
+
+    //      o 2                 
+    //     /|                   
+    //    / |                   
+    //   o 3|     n            
+    //   | -+--------->        
+    //   |  o 1                
+    //   | /                    
+    //   |/                     
+    //   o 0                    
+    //
+    //
+
+    uint_4 faceToNode;
+
+    //////////////////////////////////////////////////////////////////////////
+
+    uint posCell;
+    uint negCell;
+
+    uint posCellCoarse;
+    uint negCellCoarse;
+
+    //////////////////////////////////////////////////////////////////////////
+
+    Vec3 faceCenter;
+
+    //////////////////////////////////////////////////////////////////////////
+
+    char orientation;
+
+    bool isWall;
+
+    uint level;
+
+    MeshFace();
+};
+
+
+#endif
\ No newline at end of file
diff --git a/src/GksMeshAdapter/package.include b/src/GksMeshAdapter/package.include
new file mode 100644
index 000000000..e69de29bb
diff --git a/targets/apps/GKS/gksTest/CMakeLists.txt b/targets/apps/GKS/gksTest/CMakeLists.txt
index 836b9069e..bf204134e 100644
--- a/targets/apps/GKS/gksTest/CMakeLists.txt
+++ b/targets/apps/GKS/gksTest/CMakeLists.txt
@@ -1,8 +1,10 @@
 setTargetNameToFolderName(${CMAKE_CURRENT_LIST_DIR}) 
 
 set(linkDirectories "")
-set(libsToLink VirtualFluids_GPU GridGenerator)
-set(includeDirectories "${CMAKE_SOURCE_DIR}/src" "${CMAKE_SOURCE_DIR}/src/VirtualFluids_GPU" "${CMAKE_SOURCE_DIR}/src/GridGenerator" "${CMAKE_SOURCE_DIR}/src/VirtualFluidsBasics")
+set(libsToLink GridGenerator GksMeshAdapter)
+set(includeDirectories "${CMAKE_SOURCE_DIR}/src"
+                       "${CMAKE_SOURCE_DIR}/src/GridGenerator"
+                       "${CMAKE_SOURCE_DIR}/src/GksMeshAdapter")
 
 #glob files and save in MY_SRCS
 include(CMakePackage.cmake)
diff --git a/targets/apps/GKS/gksTest/main.cpp b/targets/apps/GKS/gksTest/main.cpp
index c36fe4fa3..7907c851f 100644
--- a/targets/apps/GKS/gksTest/main.cpp
+++ b/targets/apps/GKS/gksTest/main.cpp
@@ -1,1159 +1,104 @@
 //#define MPI_LOGGING
 
-// Stephas Branch
-
-#include <mpi.h>
-#if defined( MPI_LOGGING )
-	#include <mpe.h>
-#endif
-
 #include <string>
 #include <iostream>
-#include <stdexcept>
+#include <exception>
 #include <fstream>
 #define _USE_MATH_DEFINES
 #include <math.h>
 
-#include "metis.h"
-
-#include "Core/LbmOrGks.h"
-#include "Core/Input/Input.h"
-#include "Core/StringUtilities/StringUtil.h"
-
-#include "VirtualFluids_GPU/LBM/Simulation.h"
-#include "VirtualFluids_GPU/Communication/Communicator.h"
-#include "VirtualFluids_GPU/DataStructureInitializer/GridReaderGenerator/GridGenerator.h"
-#include "VirtualFluids_GPU/DataStructureInitializer/GridProvider.h"
-#include "VirtualFluids_GPU/DataStructureInitializer/GridReaderFiles/GridReader.h"
-#include "VirtualFluids_GPU/Parameter/Parameter.h"
-#include "VirtualFluids_GPU/Output/FileWriter.h"
+#include "core/Logger/Logger.h"
 
-#include "global.h"
+#include "GridGenerator/geometries/Cuboid/Cuboid.h"
 
-#include "geometries/Sphere/Sphere.h"
-#include "geometries/VerticalCylinder/VerticalCylinder.h"
-#include "geometries/Cuboid/Cuboid.h"
-#include "geometries/TriangularMesh/TriangularMesh.h"
-#include "geometries/Conglomerate/Conglomerate.h"
-#include "geometries/TriangularMesh/TriangularMeshStrategy.h"
+#include "GridGenerator/grid/GridBuilder/LevelGridBuilder.h"
+#include "GridGenerator/grid/GridBuilder/MultipleGridBuilder.h"
+#include "GridGenerator/grid/BoundaryConditions/Side.h"
+#include "GridGenerator/grid/BoundaryConditions/BoundaryCondition.h"
+#include "GridGenerator/grid/GridFactory.h"
 
-#include "grid/GridBuilder/LevelGridBuilder.h"
-#include "grid/GridBuilder/MultipleGridBuilder.h"
-#include "grid/BoundaryConditions/Side.h"
-#include "grid/BoundaryConditions/BoundaryCondition.h"
-#include "grid/GridFactory.h"
-
-#include "io/SimulationFileWriter/SimulationFileWriter.h"
-#include "io/GridVTKWriter/GridVTKWriter.h"
-#include "io/STLReaderWriter/STLReader.h"
-#include "io/STLReaderWriter/STLWriter.h"
-
-#include "utilities/math/Math.h"
-#include "utilities/communication.h"
-#include "utilities/transformator/TransformatorImp.h"
-
-std::string getGridPath(std::shared_ptr<Parameter> para, std::string Gridpath)
-{
-    if (para->getNumprocs() == 1)
-        return Gridpath + "/";
-    
-    return Gridpath + "/" + StringUtil::toString(para->getMyID()) + "/";
-}
+#include "GksMeshAdapter/GksMeshAdapter.h"
 
-void setParameters(std::shared_ptr<Parameter> para, std::unique_ptr<input::Input> &input)
+void gksTest()
 {
-	Communicator* comm = Communicator::getInstanz();
-
-	para->setMaxDev(StringUtil::toInt(input->getValue("NumberOfDevices")));
-	para->setNumprocs(comm->getNummberOfProcess());
-	para->setDevices(StringUtil::toVector(input->getValue("Devices")));
-	para->setMyID(comm->getPID());
-	
-	std::string _path = input->getValue("Path");
-    std::string _prefix = input->getValue("Prefix");
-    std::string _gridpath = input->getValue("GridPath");
-    std::string gridPath = getGridPath(para, _gridpath);
-    para->setOutputPath(_path);
-    para->setOutputPrefix(_prefix);
-    para->setFName(_path + "/" + _prefix);
-    para->setPrintFiles(false);
-    para->setPrintFiles(StringUtil::toBool(input->getValue("WriteGrid")));
-    para->setGeometryValues(StringUtil::toBool(input->getValue("GeometryValues")));
-    para->setCalc2ndOrderMoments(StringUtil::toBool(input->getValue("calc2ndOrderMoments")));
-    para->setCalc3rdOrderMoments(StringUtil::toBool(input->getValue("calc3rdOrderMoments")));
-    para->setCalcHighOrderMoments(StringUtil::toBool(input->getValue("calcHigherOrderMoments")));
-    para->setReadGeo(StringUtil::toBool(input->getValue("ReadGeometry")));
-    para->setCalcMedian(StringUtil::toBool(input->getValue("calcMedian")));
-    para->setConcFile(StringUtil::toBool(input->getValue("UseConcFile")));
-    para->setUseMeasurePoints(StringUtil::toBool(input->getValue("UseMeasurePoints")));
-    para->setUseWale(StringUtil::toBool(input->getValue("UseWale")));
-    para->setSimulatePorousMedia(StringUtil::toBool(input->getValue("SimulatePorousMedia")));
-    para->setD3Qxx(StringUtil::toInt(input->getValue("D3Qxx")));
-    para->setTEnd(StringUtil::toInt(input->getValue("TimeEnd")));
-    para->setTOut(StringUtil::toInt(input->getValue("TimeOut")));
-    para->setTStartOut(StringUtil::toInt(input->getValue("TimeStartOut")));
-    para->setTimeCalcMedStart(StringUtil::toInt(input->getValue("TimeStartCalcMedian")));
-    para->setTimeCalcMedEnd(StringUtil::toInt(input->getValue("TimeEndCalcMedian")));
-    para->setPressInID(StringUtil::toInt(input->getValue("PressInID")));
-    para->setPressOutID(StringUtil::toInt(input->getValue("PressOutID")));
-    para->setPressInZ(StringUtil::toInt(input->getValue("PressInZ")));
-    para->setPressOutZ(StringUtil::toInt(input->getValue("PressOutZ")));
-    //////////////////////////////////////////////////////////////////////////
-    para->setDiffOn(StringUtil::toBool(input->getValue("DiffOn")));
-    para->setDiffMod(StringUtil::toInt(input->getValue("DiffMod")));
-    para->setDiffusivity(StringUtil::toFloat(input->getValue("Diffusivity")));
-    para->setTemperatureInit(StringUtil::toFloat(input->getValue("Temp")));
-    para->setTemperatureBC(StringUtil::toFloat(input->getValue("TempBC")));
-    //////////////////////////////////////////////////////////////////////////
-    para->setViscosity(StringUtil::toFloat(input->getValue("Viscosity_LB")));
-    para->setVelocity(StringUtil::toFloat(input->getValue("Velocity_LB")));
-    para->setViscosityRatio(StringUtil::toFloat(input->getValue("Viscosity_Ratio_World_to_LB")));
-    para->setVelocityRatio(StringUtil::toFloat(input->getValue("Velocity_Ratio_World_to_LB")));
-    para->setDensityRatio(StringUtil::toFloat(input->getValue("Density_Ratio_World_to_LB")));
-    para->setPressRatio(StringUtil::toFloat(input->getValue("Delta_Press")));
-    para->setRealX(StringUtil::toFloat(input->getValue("SliceRealX")));
-    para->setRealY(StringUtil::toFloat(input->getValue("SliceRealY")));
-    para->setFactorPressBC(StringUtil::toFloat(input->getValue("dfpbc")));
-    para->setGeometryFileC(input->getValue("GeometryC"));
-    para->setGeometryFileM(input->getValue("GeometryM"));
-    para->setGeometryFileF(input->getValue("GeometryF"));
-    //////////////////////////////////////////////////////////////////////////
-    para->setgeoVec(gridPath + input->getValue("geoVec"));
-    para->setcoordX(gridPath + input->getValue("coordX"));
-    para->setcoordY(gridPath + input->getValue("coordY"));
-    para->setcoordZ(gridPath + input->getValue("coordZ"));
-    para->setneighborX(gridPath + input->getValue("neighborX"));
-    para->setneighborY(gridPath + input->getValue("neighborY"));
-    para->setneighborZ(gridPath + input->getValue("neighborZ"));
-    para->setscaleCFC(gridPath + input->getValue("scaleCFC"));
-    para->setscaleCFF(gridPath + input->getValue("scaleCFF"));
-    para->setscaleFCC(gridPath + input->getValue("scaleFCC"));
-    para->setscaleFCF(gridPath + input->getValue("scaleFCF"));
-    para->setscaleOffsetCF(gridPath + input->getValue("scaleOffsetCF"));
-    para->setscaleOffsetFC(gridPath + input->getValue("scaleOffsetFC"));
-    para->setgeomBoundaryBcQs(gridPath + input->getValue("geomBoundaryBcQs"));
-    para->setgeomBoundaryBcValues(gridPath + input->getValue("geomBoundaryBcValues"));
-    para->setinletBcQs(gridPath + input->getValue("inletBcQs"));
-    para->setinletBcValues(gridPath + input->getValue("inletBcValues"));
-    para->setoutletBcQs(gridPath + input->getValue("outletBcQs"));
-    para->setoutletBcValues(gridPath + input->getValue("outletBcValues"));
-    para->settopBcQs(gridPath + input->getValue("topBcQs"));
-    para->settopBcValues(gridPath + input->getValue("topBcValues"));
-    para->setbottomBcQs(gridPath + input->getValue("bottomBcQs"));
-    para->setbottomBcValues(gridPath + input->getValue("bottomBcValues"));
-    para->setfrontBcQs(gridPath + input->getValue("frontBcQs"));
-    para->setfrontBcValues(gridPath + input->getValue("frontBcValues"));
-    para->setbackBcQs(gridPath + input->getValue("backBcQs"));
-    para->setbackBcValues(gridPath + input->getValue("backBcValues"));
-    para->setnumberNodes(gridPath + input->getValue("numberNodes"));
-    para->setLBMvsSI(gridPath + input->getValue("LBMvsSI"));
-    //////////////////////////////gridPath + ////////////////////////////////////////////
-    para->setmeasurePoints(gridPath + input->getValue("measurePoints"));
-    para->setpropellerValues(gridPath + input->getValue("propellerValues"));
-    para->setclockCycleForMP(StringUtil::toFloat(input->getValue("measureClockCycle")));
-    para->settimestepForMP(StringUtil::toInt(input->getValue("measureTimestep")));
-    para->setcpTop(gridPath + input->getValue("cpTop"));
-    para->setcpBottom(gridPath + input->getValue("cpBottom"));
-    para->setcpBottom2(gridPath + input->getValue("cpBottom2"));
-    para->setConcentration(gridPath + input->getValue("Concentration"));
-    //////////////////////////////////////////////////////////////////////////
-    //Normals - Geometry
-    para->setgeomBoundaryNormalX(gridPath + input->getValue("geomBoundaryNormalX"));
-    para->setgeomBoundaryNormalY(gridPath + input->getValue("geomBoundaryNormalY"));
-    para->setgeomBoundaryNormalZ(gridPath + input->getValue("geomBoundaryNormalZ"));
-    //Normals - Inlet
-    para->setInflowBoundaryNormalX(gridPath + input->getValue("inletBoundaryNormalX"));
-    para->setInflowBoundaryNormalY(gridPath + input->getValue("inletBoundaryNormalY"));
-    para->setInflowBoundaryNormalZ(gridPath + input->getValue("inletBoundaryNormalZ"));
-    //Normals - Outlet
-    para->setOutflowBoundaryNormalX(gridPath + input->getValue("outletBoundaryNormalX"));
-    para->setOutflowBoundaryNormalY(gridPath + input->getValue("outletBoundaryNormalY"));
-    para->setOutflowBoundaryNormalZ(gridPath + input->getValue("outletBoundaryNormalZ"));
-    //////////////////////////////////////////////////////////////////////////
-    //Forcing
-    para->setForcing(StringUtil::toFloat(input->getValue("ForcingX")), StringUtil::toFloat(input->getValue("ForcingY")), StringUtil::toFloat(input->getValue("ForcingZ")));
-    //////////////////////////////////////////////////////////////////////////
-    //Particles
-    para->setCalcParticles(StringUtil::toBool(input->getValue("calcParticles")));
-    para->setParticleBasicLevel(StringUtil::toInt(input->getValue("baseLevel")));
-    para->setParticleInitLevel(StringUtil::toInt(input->getValue("initLevel")));
-    para->setNumberOfParticles(StringUtil::toInt(input->getValue("numberOfParticles")));
-    para->setneighborWSB(gridPath + input->getValue("neighborWSB"));
-    para->setStartXHotWall(StringUtil::toDouble(input->getValue("startXHotWall")));
-    para->setEndXHotWall(StringUtil::toDouble(input->getValue("endXHotWall")));
-    //////////////////////////////////////////////////////////////////////////
-    //for Multi GPU
-    if (para->getNumprocs() > 1)
-    {
-        ////////////////////////////////////////////////////////////////////////////
-        ////1D domain decomposition
-        //std::vector<std::string> sendProcNeighbors;
-        //std::vector<std::string> recvProcNeighbors;
-        //for (int i = 0; i<para->getNumprocs();i++)
-        //{
-        // sendProcNeighbors.push_back(gridPath + StringUtil::toString(i) + "s.dat");
-        // recvProcNeighbors.push_back(gridPath + StringUtil::toString(i) + "r.dat");
-        //}
-        //para->setPossNeighborFiles(sendProcNeighbors, "send");
-        //para->setPossNeighborFiles(recvProcNeighbors, "recv");
-        //////////////////////////////////////////////////////////////////////////
-        //3D domain decomposition
-        std::vector<std::string> sendProcNeighborsX, sendProcNeighborsY, sendProcNeighborsZ;
-        std::vector<std::string> recvProcNeighborsX, recvProcNeighborsY, recvProcNeighborsZ;
-        for (int i = 0; i < para->getNumprocs(); i++)
-        {
-            sendProcNeighborsX.push_back(gridPath + StringUtil::toString(i) + "Xs.dat");
-            sendProcNeighborsY.push_back(gridPath + StringUtil::toString(i) + "Ys.dat");
-            sendProcNeighborsZ.push_back(gridPath + StringUtil::toString(i) + "Zs.dat");
-            recvProcNeighborsX.push_back(gridPath + StringUtil::toString(i) + "Xr.dat");
-            recvProcNeighborsY.push_back(gridPath + StringUtil::toString(i) + "Yr.dat");
-            recvProcNeighborsZ.push_back(gridPath + StringUtil::toString(i) + "Zr.dat");
-        }
-        para->setPossNeighborFilesX(sendProcNeighborsX, "send");
-        para->setPossNeighborFilesY(sendProcNeighborsY, "send");
-        para->setPossNeighborFilesZ(sendProcNeighborsZ, "send");
-        para->setPossNeighborFilesX(recvProcNeighborsX, "recv");
-        para->setPossNeighborFilesY(recvProcNeighborsY, "recv");
-        para->setPossNeighborFilesZ(recvProcNeighborsZ, "recv");
-    }
-    //////////////////////////////////////////////////////////////////////////
-    //para->setkFull(             input->getValue( "kFull" ));
-    //para->setgeoFull(           input->getValue( "geoFull" ));
-    //para->setnoSlipBcPos(       input->getValue( "noSlipBcPos" ));
-    //para->setnoSlipBcQs(          input->getValue( "noSlipBcQs" ));
-    //para->setnoSlipBcValues(      input->getValue( "noSlipBcValues" ));
-    //para->setnoSlipBcValue(     input->getValue( "noSlipBcValue" ));
-    //para->setslipBcPos(         input->getValue( "slipBcPos" ));
-    //para->setslipBcQs(          input->getValue( "slipBcQs" ));
-    //para->setslipBcValue(       input->getValue( "slipBcValue" ));
-    //para->setpressBcPos(        input->getValue( "pressBcPos" ));
-    //para->setpressBcQs(           input->getValue( "pressBcQs" ));
-    //para->setpressBcValues(       input->getValue( "pressBcValues" ));
-    //para->setpressBcValue(      input->getValue( "pressBcValue" ));
-    //para->setvelBcQs(             input->getValue( "velBcQs" ));
-    //para->setvelBcValues(         input->getValue( "velBcValues" ));
-    //para->setpropellerCylinder( input->getValue( "propellerCylinder" ));
-    //para->setpropellerQs(		 input->getValue( "propellerQs"      ));
-    //para->setwallBcQs(            input->getValue( "wallBcQs"         ));
-    //para->setwallBcValues(        input->getValue( "wallBcValues"     ));
-    //para->setperiodicBcQs(        input->getValue( "periodicBcQs"     ));
-    //para->setperiodicBcValues(    input->getValue( "periodicBcValues" ));
-    //cout << "Try this: " << para->getgeomBoundaryBcValues() << endl;
-
-    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-    //Restart
-    para->setTimeDoCheckPoint(StringUtil::toInt(input->getValue("TimeDoCheckPoint")));
-    para->setTimeDoRestart(StringUtil::toInt(input->getValue("TimeDoRestart")));
-    para->setDoCheckPoint(StringUtil::toBool(input->getValue("DoCheckPoint")));
-    para->setDoRestart(StringUtil::toBool(input->getValue("DoRestart")));
-    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-    para->setMaxLevel(StringUtil::toInt(input->getValue("NOGL")));
-    para->setGridX(StringUtil::toVector(input->getValue("GridX")));                           
-    para->setGridY(StringUtil::toVector(input->getValue("GridY")));                           
-    para->setGridZ(StringUtil::toVector(input->getValue("GridZ")));                  
-    para->setDistX(StringUtil::toVector(input->getValue("DistX")));                  
-    para->setDistY(StringUtil::toVector(input->getValue("DistY")));                  
-    para->setDistZ(StringUtil::toVector(input->getValue("DistZ")));                
-
-    para->setNeedInterface(std::vector<bool>{true, true, true, true, true, true});
-}
-
-
-
-void multipleLevel(const std::string& configPath)
-{
-    //std::ofstream logFile( "F:/Work/Computations/gridGenerator/grid/gridGeneratorLog.txt" );
-    std::ofstream logFile( "grid/gridGeneratorLog.txt" );
-    logging::Logger::addStream(&logFile);
-
-    logging::Logger::addStream(&std::cout);
-    logging::Logger::setDebugLevel(logging::Logger::Level::INFO_LOW);
-    logging::Logger::timeStamp(logging::Logger::ENABLE);
-    logging::Logger::enablePrintedRankNumbers(logging::Logger::ENABLE);
-
-    //UbLog::reportingLevel() = UbLog::logLevelFromString("DEBUG5");
-
     auto gridFactory = GridFactory::make();
     gridFactory->setGridStrategy(Device::CPU);
-    //gridFactory->setTriangularMeshDiscretizationMethod(TriangularMeshDiscretizationMethod::RAYCASTING);
     gridFactory->setTriangularMeshDiscretizationMethod(TriangularMeshDiscretizationMethod::POINT_IN_OBJECT);
-    //gridFactory->setTriangularMeshDiscretizationMethod(TriangularMeshDiscretizationMethod::POINT_UNDER_TRIANGLE);
 
     auto gridBuilder = MultipleGridBuilder::makeShared(gridFactory);
-    
-    SPtr<Parameter> para = Parameter::make();
-    SPtr<GridProvider> gridGenerator;
 
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-    bool useGridGenerator = true;
-
-    if(useGridGenerator){
-
-        enum testCase{ 
-            DrivAer,
-            DLC,
-            MultiGPU,
-            MetisTest
-        };
-
-        int testcase = MetisTest;
-        
-        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-        if( testcase == DrivAer )
-        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-        {
-            real dx = 0.2;
-            real vx = 0.05;
-
-            TriangularMesh* DrivAerSTL = TriangularMesh::make("F:/Work/Computations/gridGenerator/stl/DrivAer_Fastback_Coarse.stl");
-            //TriangularMesh* triangularMesh = TriangularMesh::make("M:/TestGridGeneration/STL/DrivAer_NoSTLGroups.stl");
-            //TriangularMesh* triangularMesh = TriangularMesh::make("M:/TestGridGeneration/STL/DrivAer_Coarse.stl");
-            //TriangularMesh* DrivAerSTL = TriangularMesh::make("stl/DrivAer_Fastback_Coarse.stl");
-
-            TriangularMesh* DrivAerRefBoxSTL = TriangularMesh::make("F:/Work/Computations/gridGenerator/stl/DrivAer_REF_BOX_Adrea.stl");
-            //TriangularMesh* DrivAerRefBoxSTL = TriangularMesh::make("stl/DrivAer_REF_BOX_Adrea.stl");
-
-            real z0 = 0.318+0.5*dx;
-
-            gridBuilder->addCoarseGrid(- 5.0, -5.0, 0.0 - z0,
-                                        15.0,  5.0, 5.0 - z0, dx);  // DrivAer
-
-            //Object* floorBox = new Cuboid( -0.3, -1, -1, 4.0, 1, 0.2 );
-            //Object* wakeBox  = new Cuboid(  3.5, -1, -1, 5.5, 1, 0.8 );
-
-            //Conglomerate* refRegion = new Conglomerate();
-
-            //refRegion->add(floorBox);
-            //refRegion->add(wakeBox);
-            //refRegion->add(DrivAerRefBoxSTL);
-
-            gridBuilder->setNumberOfLayers(10,8);
-            gridBuilder->addGrid(DrivAerRefBoxSTL, 2);
-        
-            //gridBuilder->setNumberOfLayers(10,8);
-            //gridBuilder->addGrid(DrivAerSTL, 5);
-
-            gridBuilder->addGeometry(DrivAerSTL);
-
-            gridBuilder->setPeriodicBoundaryCondition(false, false, false);
-
-            gridBuilder->buildGrids(LBM, true); // buildGrids() has to be called before setting the BCs!!!!
-
-            //////////////////////////////////////////////////////////////////////////
-
-            gridBuilder->setVelocityBoundaryCondition(SideType::PY, vx , 0.0, 0.0);
-            gridBuilder->setVelocityBoundaryCondition(SideType::MY, vx , 0.0, 0.0);
-            gridBuilder->setVelocityBoundaryCondition(SideType::PZ, vx , 0.0, 0.0);
-            gridBuilder->setVelocityBoundaryCondition(SideType::MZ, vx , 0.0, 0.0);
-
-            gridBuilder->setPressureBoundaryCondition(SideType::PX, 0.0);
-            gridBuilder->setVelocityBoundaryCondition(SideType::MX, vx, 0.0, 0.0);
-
-            gridBuilder->setVelocityBoundaryCondition(SideType::GEOMETRY, 0.0, 0.0, 0.0);
-            
-            //////////////////////////////////////////////////////////////////////////
-
-            SPtr<Grid> grid = gridBuilder->getGrid(gridBuilder->getNumberOfLevels() - 1);
-
-            gridBuilder->getGeometryBoundaryCondition(gridBuilder->getNumberOfLevels() - 1)->setTangentialVelocityForPatch( grid, 4, 0.0075, -2.0, 0.0,
-                                                                                                                                     0.0075,  2.0, 0.0, -vx, 0.318);
-            gridBuilder->getGeometryBoundaryCondition(gridBuilder->getNumberOfLevels() - 1)->setTangentialVelocityForPatch( grid, 3, 2.793 , -2.0, 0.0,
-                                                                                                                                     2.793 ,  2.0, 0.0, -vx, 0.318);
-
-            //////////////////////////////////////////////////////////////////////////
-
-            gridBuilder->writeGridsToVtk("F:/Work/Computations/gridGenerator/grid/DrivAer_Grid");
-            gridBuilder->writeArrows    ("F:/Work/Computations/gridGenerator/grid/DrivAer_Grid_arrow");
-
-            //SimulationFileWriter::write("D:/GRIDGENERATION/files/", gridBuilder, FILEFORMAT::ASCII);
-            //SimulationFileWriter::write("C:/Users/lenz/Desktop/Work/gridGenerator/grid/", gridBuilder, FILEFORMAT::ASCII);
-            SimulationFileWriter::write("F:/Work/Computations/gridGenerator/grid/", gridBuilder, FILEFORMAT::BINARY);
-            //SimulationFileWriter::write("grid/", gridBuilder, FILEFORMAT::ASCII);
-
-            return;
-
-            gridGenerator = GridGenerator::make(gridBuilder, para);
-        }
-
-        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-        if( testcase == DLC )
-        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-        {
-			real velocityRatio = 594.093427;
-
-			real dx = 0.2;
-			real vx = 0.065272188;
-
-			real z0 = 0.24395 + 0.5*dx;
-
-            std::vector<uint> ignorePatches = { 152, 153, 154 };
-
-            //TriangularMesh* VW370_SERIE_STL = TriangularMesh::make("C:/Users/lenz/Desktop/Work/gridGenerator/stl/VW370_SERIE.stl", ignorePatches);
-            TriangularMesh* VW370_SERIE_STL = TriangularMesh::make("stl/VW370_SERIE.stl", ignorePatches);
-
-            //TriangularMesh* DLC_RefBox = TriangularMesh::make("C:/Users/lenz/Desktop/Work/gridGenerator/stl/DLC_RefBox.stl");
-
-            //TriangularMesh* DLC_RefBox_1 = TriangularMesh::make("C:/Users/lenz/Desktop/Work/gridGenerator/stl/DLC_RefBox_withWake/DLC_RefBox_withWake_4m.stl");
-            //TriangularMesh* DLC_RefBox_2 = TriangularMesh::make("C:/Users/lenz/Desktop/Work/gridGenerator/stl/DLC_RefBox_withWake/DLC_RefBox_withWake_3m.stl");
-            //TriangularMesh* DLC_RefBox_3 = TriangularMesh::make("C:/Users/lenz/Desktop/Work/gridGenerator/stl/DLC_RefBox_withWake/DLC_RefBox_withWake_2m.stl");
-            //TriangularMesh* DLC_RefBox_4 = TriangularMesh::make("C:/Users/lenz/Desktop/Work/gridGenerator/stl/DLC_RefBox_withWake/DLC_RefBox_withWake_1m.stl");
-
-            //TriangularMesh* DLC_RefBox_Level_3 = TriangularMesh::make("C:/Users/lenz/Desktop/Work/gridGenerator/stl/DLC/DLC_RefBox_Level_3.stl");
-            //TriangularMesh* DLC_RefBox_Level_4 = TriangularMesh::make("C:/Users/lenz/Desktop/Work/gridGenerator/stl/DLC/DLC_RefBox_Level_4.stl");
-            //TriangularMesh* DLC_RefBox_Level_5 = TriangularMesh::make("C:/Users/lenz/Desktop/Work/gridGenerator/stl/DLC/DLC_RefBox_Level_5.stl");
-
-            TriangularMesh* DLC_RefBox_Level_3 = TriangularMesh::make("stl/DLC/DLC_RefBox_Level_3.stl");
-            TriangularMesh* DLC_RefBox_Level_4 = TriangularMesh::make("stl/DLC/DLC_RefBox_Level_4.stl");
-            TriangularMesh* DLC_RefBox_Level_5 = TriangularMesh::make("stl/DLC/DLC_RefBox_Level_5.stl");
-
-            //TriangularMesh* VW370_SERIE_STL = TriangularMesh::make("stl/VW370_SERIE.stl", ignorePatches);
-            //TriangularMesh* DLC_RefBox = TriangularMesh::make("stl/DLC_RefBox.lnx.stl");
-            //TriangularMesh* DLC_RefBox_4 = TriangularMesh::make("stl/DLC_RefBox_withWake/DLC_RefBox_withWake_1m.lnx.stl");
-
-            gridBuilder->addCoarseGrid(-30.0, -20.0,  0.0 - z0,
-                                        50.0,  20.0, 25.0 - z0, dx);
-            
-            gridBuilder->setNumberOfLayers(10,8);
-            gridBuilder->addGrid( new Cuboid( - 6.6, -6, -0.7, 20.6 , 6, 5.3  ), 1 );
-            gridBuilder->addGrid( new Cuboid( -3.75, -3, -0.7, 11.75, 3, 2.65 ), 2 );
-
-            gridBuilder->setNumberOfLayers(10,8);
-            gridBuilder->addGrid(DLC_RefBox_Level_3, 3);
-            gridBuilder->addGrid(DLC_RefBox_Level_4, 4);
-        
-            Conglomerate* refinement = new Conglomerate();
-            refinement->add(DLC_RefBox_Level_5);
-            refinement->add(VW370_SERIE_STL);
-
-            gridBuilder->setNumberOfLayers(10,8);
-            gridBuilder->addGrid(refinement, 5);
-
-            gridBuilder->addGeometry(VW370_SERIE_STL);
-
-            gridBuilder->setPeriodicBoundaryCondition(false, false, false);
-
-            gridBuilder->buildGrids(LBM, true); // buildGrids() has to be called before setting the BCs!!!!
-
-            //////////////////////////////////////////////////////////////////////////
-
-            gridBuilder->setVelocityBoundaryCondition(SideType::PY, vx , 0.0, 0.0);
-            gridBuilder->setVelocityBoundaryCondition(SideType::MY, vx , 0.0, 0.0);
-            gridBuilder->setVelocityBoundaryCondition(SideType::PZ, vx , 0.0, 0.0);
-            gridBuilder->setVelocityBoundaryCondition(SideType::MZ, vx , 0.0, 0.0);
-
-            gridBuilder->setPressureBoundaryCondition(SideType::PX, 0.0);
-            gridBuilder->setVelocityBoundaryCondition(SideType::MX, vx, 0.0, 0.0);
-
-            gridBuilder->setVelocityBoundaryCondition(SideType::GEOMETRY, 0.0, 0.0, 0.0);
-            
-            //////////////////////////////////////////////////////////////////////////
-
-            SPtr<Grid> grid = gridBuilder->getGrid(gridBuilder->getNumberOfLevels() - 1);
-
-            real wheelsFrontX = -0.081;
-            real wheelsRearX  =  2.5486;
-
-            real wheelsFrontZ =  0.0504;
-            real wheelsRearZ  =  0.057;
-
-            real wheelsRadius =  0.318;
-
-			real wheelRotationFrequency = 1170.74376 / 60.0;
-
-			real wheelTangentialVelocity = -2.0 * M_PI * wheelsRadius * wheelRotationFrequency / velocityRatio;
-
-            std::vector<uint> frontWheelPatches = { 71, 86, 87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97, 159 };
-            std::vector<uint> rearWheelPatches  = { 82, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 160 };
-
-            for( uint patch : frontWheelPatches ){
-                gridBuilder->getGeometryBoundaryCondition(gridBuilder->getNumberOfLevels() - 1)->setTangentialVelocityForPatch( grid, patch, wheelsFrontX, -2.0, wheelsFrontZ,
-                                                                                                                                             wheelsFrontX,  2.0, wheelsFrontZ, 
-					                                                                                                                         wheelTangentialVelocity, wheelsRadius);
-            }
-
-            for( uint patch : rearWheelPatches ){
-                gridBuilder->getGeometryBoundaryCondition(gridBuilder->getNumberOfLevels() - 1)->setTangentialVelocityForPatch( grid, patch, wheelsRearX , -2.0, wheelsRearZ ,
-                                                                                                                                             wheelsRearX ,  2.0, wheelsRearZ , 
-					                                                                                                                         wheelTangentialVelocity, wheelsRadius);
-            }
-
-            //////////////////////////////////////////////////////////////////////////
-
-            //gridBuilder->writeGridsToVtk("C:/Users/lenz/Desktop/Work/gridGenerator/grid/DLC_Grid");
-            //gridBuilder->writeArrows    ("C:/Users/lenz/Desktop/Work/gridGenerator/grid/DLC_Grid_arrow");
-
-            gridBuilder->writeGridsToVtk("grid/DLC_Grid");
-            gridBuilder->writeArrows    ("grid/DLC_Grid_arrow");
-
-            //SimulationFileWriter::write("D:/GRIDGENERATION/files/", gridBuilder, FILEFORMAT::ASCII);
-            //SimulationFileWriter::write("C:/Users/lenz/Desktop/Work/gridGenerator/grid/", gridBuilder, FILEFORMAT::ASCII);
-            SimulationFileWriter::write("grid/", gridBuilder, FILEFORMAT::ASCII);
-
-            gridGenerator = GridGenerator::make(gridBuilder, para);
-        }
-
-        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-        if( testcase == MultiGPU )
-        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-        {
-            //const uint generatePart = 1;
-            const uint generatePart = Communicator::getInstanz()->getPID();
-            
-            std::ofstream logFile2;
-            
-            if( generatePart == 0 )
-                //logFile2.open( "F:/Work/Computations/gridGenerator/grid/0/gridGeneratorLog.txt" );
-                logFile2.open( "grid/0/gridGeneratorLog.txt" );
-            
-            if( generatePart == 1 )
-                //logFile2.open( "F:/Work/Computations/gridGenerator/grid/1/gridGeneratorLog.txt" );
-                logFile2.open( "grid/1/gridGeneratorLog.txt" );
-
-            logging::Logger::addStream(&logFile2);
-
-            real dx = 1.0 / 40.0;
-            real vx = 0.05;
-
-            //TriangularMesh* triangularMesh = TriangularMesh::make("F:/Work/Computations/gridGenerator/stl/ShpereNotOptimal.stl");
-            TriangularMesh* triangularMesh = TriangularMesh::make("stl/ShpereNotOptimal.lnx.stl");
-
-            // all
-            //gridBuilder->addCoarseGrid(-2, -2, -2,  
-            //                            4,  2,  2, dx);
-
-            real overlap = 10.0 * dx;
-
-            if( generatePart == 0 )
-                gridBuilder->addCoarseGrid(-2.0          , -2.0, -2.0,  
-                                            0.5 + overlap,  2.0,  2.0, dx);
-
-            if( generatePart == 1 )
-                gridBuilder->addCoarseGrid( 0.5 - overlap, -2.0, -2.0,  
-                                            4.0          ,  2.0,  2.0, dx);
-
-
-            gridBuilder->setNumberOfLayers(10,8);
-            gridBuilder->addGrid(triangularMesh, 1);
-
-            gridBuilder->addGeometry(triangularMesh);
-            
-            if( generatePart == 0 )
-                gridBuilder->setSubDomainBox( std::make_shared<BoundingBox>( -2.0, 0.5, 
-                                                                             -2.0, 2.0, 
-                                                                             -2.0, 2.0 ) );
-            
-            if( generatePart == 1 )
-                gridBuilder->setSubDomainBox( std::make_shared<BoundingBox>(  0.5, 4.0, 
-                                                                             -2.0, 2.0, 
-                                                                             -2.0, 2.0 ) );
-
-            gridBuilder->setPeriodicBoundaryCondition(false, false, false);
-
-            gridBuilder->buildGrids(LBM, true); // buildGrids() has to be called before setting the BCs!!!!
-            
-            if( generatePart == 0 ){
-                gridBuilder->findCommunicationIndices(CommunicationDirections::PX);
-                gridBuilder->setCommunicationProcess(CommunicationDirections::PX, 1);
-            }
-            
-            if( generatePart == 1 ){
-                gridBuilder->findCommunicationIndices(CommunicationDirections::MX);
-                gridBuilder->setCommunicationProcess(CommunicationDirections::MX, 0);
-            }
-
-            //////////////////////////////////////////////////////////////////////////
-
-            gridBuilder->setVelocityBoundaryCondition(SideType::PY, vx , 0.0, 0.0);
-            gridBuilder->setVelocityBoundaryCondition(SideType::MY, vx , 0.0, 0.0);
-            gridBuilder->setVelocityBoundaryCondition(SideType::PZ, vx , 0.0, 0.0);
-            gridBuilder->setVelocityBoundaryCondition(SideType::MZ, vx , 0.0, 0.0);
-
-            if (generatePart == 0) {
-                gridBuilder->setVelocityBoundaryCondition(SideType::MX, vx, 0.0, 0.0);
-            }
-            if (generatePart == 1) {
-                gridBuilder->setPressureBoundaryCondition(SideType::PX, 0.0);
-            }
-
-            gridBuilder->setVelocityBoundaryCondition(SideType::GEOMETRY, 0.0, 0.0, 0.0);
-        
-            //////////////////////////////////////////////////////////////////////////
-
-            if (generatePart == 0) {
-                //gridBuilder->writeGridsToVtk("F:/Work/Computations/gridGenerator/grid/0/Test_");
-                //gridBuilder->writeArrows    ("F:/Work/Computations/gridGenerator/grid/0/Test_Arrow");
-            }
-            if (generatePart == 1) {
-                //gridBuilder->writeGridsToVtk("F:/Work/Computations/gridGenerator/grid/1/Test_");
-                //gridBuilder->writeArrows    ("F:/Work/Computations/gridGenerator/grid/1/Test_Arrow");
-            }
-
-            if (generatePart == 0)
-                //SimulationFileWriter::write("F:/Work/Computations/gridGenerator/grid/0/", gridBuilder, FILEFORMAT::ASCII);
-                SimulationFileWriter::write("grid/0/", gridBuilder, FILEFORMAT::ASCII);
-            if (generatePart == 1)
-                //SimulationFileWriter::write("F:/Work/Computations/gridGenerator/grid/1/", gridBuilder, FILEFORMAT::ASCII);
-                SimulationFileWriter::write("grid/1/", gridBuilder, FILEFORMAT::ASCII);
-
-            //return;
-
-            gridGenerator = GridGenerator::make(gridBuilder, para);
-        }
-
-        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-        if( testcase == MetisTest )
-        //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-        {
-            //const uint generatePart = 1;
-            const uint generatePart = Communicator::getInstanz()->getPID();
-            
-            real dx = 1.0 / 20.0;
-            real vx = 0.05;
-
-            TriangularMesh* triangularMesh = TriangularMesh::make("F:/Work/Computations/gridGenerator/stl/ShpereNotOptimal.stl");
-            //TriangularMesh* triangularMesh = TriangularMesh::make("stl/ShpereNotOptimal.lnx.stl");
-
-            // all
-            //gridBuilder->addCoarseGrid(-2, -2, -2,  
-            //                            4,  2,  2, dx);
-
-            real overlap = 10.0 * dx;
-
-            gridBuilder->addCoarseGrid(-2.0, -2.0, -2.0,  
-                                        4.0,  2.0,  2.0, dx);
-
-
-            gridBuilder->setNumberOfLayers(10,8);
-            gridBuilder->addGrid(triangularMesh, 1);
-
-            gridBuilder->addGeometry(triangularMesh);
-
-            gridBuilder->setPeriodicBoundaryCondition(false, false, false);
-
-            gridBuilder->buildGrids(LBM, true); // buildGrids() has to be called before setting the BCs!!!!
-
-            //////////////////////////////////////////////////////////////////////////
 
-            gridBuilder->setVelocityBoundaryCondition(SideType::PY, vx , 0.0, 0.0);
-            gridBuilder->setVelocityBoundaryCondition(SideType::MY, vx , 0.0, 0.0);
-            gridBuilder->setVelocityBoundaryCondition(SideType::PZ, vx , 0.0, 0.0);
-            gridBuilder->setVelocityBoundaryCondition(SideType::MZ, vx , 0.0, 0.0);
+    real dx = 1.0 / 32.0;
 
-            gridBuilder->setVelocityBoundaryCondition(SideType::MX, vx, 0.0, 0.0);
-            gridBuilder->setPressureBoundaryCondition(SideType::PX, 0.0);
+    gridBuilder->addCoarseGrid(-0.5, -0.5, -0.5,  
+                                0.5,  0.5,  0.5, dx);
 
-            gridBuilder->setVelocityBoundaryCondition(SideType::GEOMETRY, 0.0, 0.0, 0.0);
-        
-            //////////////////////////////////////////////////////////////////////////
+    Cuboid cube(-1.0, -1.0, 0.45, 1.0, 1.0, 0.55);
 
-            gridBuilder->writeGridsToVtk("F:/Work/Computations/gridGenerator/grid/Test_");
-            //gridBuilder->writeArrows    ("F:/Work/Computations/gridGenerator/grid/Test_Arrow");
+    gridBuilder->setNumberOfLayers(10,8);
+    gridBuilder->addGrid( &cube, 1);
 
-            //SimulationFileWriter::write("F:/Work/Computations/gridGenerator/grid/", gridBuilder, FILEFORMAT::ASCII);
+    gridBuilder->setPeriodicBoundaryCondition(false, false, false);
 
-            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-            
-            if(false)
-            {
+    gridBuilder->buildGrids(GKS, false);
 
-                auto getParentIndex = [&] (uint index, uint level) -> uint
-                {
-                    SPtr<Grid> grid = gridBuilder->getGrid( level );
+    gridBuilder->writeGridsToVtk("F:/Work/Computations/gridGenerator/grid/Grid_lev_");
 
-                    if( level != 0 )
-                    {
-                        real x, y, z;
-                        grid->transIndexToCoords(index, x, y, z);
-
-                        SPtr<Grid> coarseGrid = gridBuilder->getGrid(level - 1);
-
-                        for (const auto dir : DistributionHelper::getDistribution27())
-                        {
-                            if (std::abs(dir[0]) < 0.5 || std::abs(dir[1]) < 0.5 || std::abs(dir[2]) < 0.5) continue;
-
-                            real coarseX = x + dir[0] * 0.5 * grid->getDelta();
-                            real coarseY = y + dir[1] * 0.5 * grid->getDelta();
-                            real coarseZ = z + dir[2] * 0.5 * grid->getDelta();
-
-                            // check if close enough to coarse grid coordinates
-                            if( 0.01 * grid->getDelta() < std::abs(         (coarseGrid->getStartX() - coarseX) / grid->getDelta() 
-                                                                  - lround( (coarseGrid->getStartX() - coarseX) / grid->getDelta() ) ) ) continue;
-                            if( 0.01 * grid->getDelta() < std::abs(         (coarseGrid->getStartY() - coarseY) / grid->getDelta() 
-                                                                  - lround( (coarseGrid->getStartY() - coarseY) / grid->getDelta() ) ) ) continue;
-                            if( 0.01 * grid->getDelta() < std::abs(         (coarseGrid->getStartZ() - coarseZ) / grid->getDelta() 
-                                                                  - lround( (coarseGrid->getStartZ() - coarseZ) / grid->getDelta() ) ) ) continue;
-
-                            uint parentIndex = coarseGrid->transCoordToIndex( coarseX, coarseY, coarseZ);
-
-                            return parentIndex;
-                        }
-                    }
-
-                    return INVALID_INDEX;
-                };
-
-
-                std::vector<idx_t> xadj;
-                std::vector<idx_t> adjncy;
-
-                std::vector<idx_t> vwgt;
-                std::vector<idx_t> adjwgt;
-
-                idx_t vertexCounter = 0;
-                uint edgeCounter = 0;
-
-                std::cout << "Checkpoint 1:" << std::endl;
-
-                std::vector< std::vector<idx_t> > vertexIndex( gridBuilder->getNumberOfLevels() );
-
-                std::vector< uint > startVerticesPerLevel;;
-
-                for( uint level = 0; level < gridBuilder->getNumberOfLevels(); level++ )
-                {
-                    SPtr<Grid> grid = gridBuilder->getGrid( level );
-
-                    vertexIndex[level].resize( grid->getSize() );
-
-                    startVerticesPerLevel.push_back(vertexCounter);
-
-                    for (uint index = 0; index < grid->getSize(); index++)
-                    {
-                        if (grid->getSparseIndex(index) == INVALID_INDEX)
-                        {
-                            vertexIndex[level][index] = INVALID_INDEX;
-                            continue;
-                        }
-
-                        uint parentIndex = getParentIndex(index, level);
-
-                        if( parentIndex != INVALID_INDEX )
-                        {
-                            SPtr<Grid> coarseGrid = gridBuilder->getGrid(level - 1);
-
-                            if( coarseGrid->getFieldEntry(parentIndex) == FLUID_CFC ||
-                                coarseGrid->getFieldEntry(parentIndex) == FLUID_FCC ||
-                                coarseGrid->getFieldEntry(parentIndex) == STOPPER_COARSE_UNDER_FINE )
-                            {
-                                //vertexIndex[level][index] = INVALID_INDEX;
-                                vertexIndex[level][index] = vertexIndex[level - 1][parentIndex];
-                                continue;
-                            }
-                        }
-
-                        vertexIndex[level][index] = vertexCounter;
-
-                        vwgt.push_back( std::pow(2, level) );
-                        //vwgt.push_back( std::pow(2, 2*level) );
-                        vertexCounter++;
-                    }
-
-                }
-
-                //////////////////////////////////////////////////////////////////////////
-                //for( uint level = 0; level < gridBuilder->getNumberOfLevels(); level++ )
-                //{
-                //    SPtr<Grid> grid = gridBuilder->getGrid( level );
-
-                //    for (uint index = 0; index < grid->getSize(); index++)
-                //    {
-                //        grid->setFieldEntry(index, vertexIndex[level][index] >= startVerticesPerLevel[level] && vertexIndex[level][index] != INVALID_INDEX);
-                //    }
-                //}
-
-                //gridBuilder->writeGridsToVtk("F:/Work/Computations/gridGenerator/grid/VertexIndex_");
-
-                //return;
-                //////////////////////////////////////////////////////////////////////////
-
-
-                std::cout << "Checkpoint 2:" << std::endl;
-                
-                for( uint level = 0; level < gridBuilder->getNumberOfLevels(); level++ )
-                {
-                    SPtr<Grid> grid = gridBuilder->getGrid( level );
-
-                    for (uint index = 0; index < grid->getSize(); index++)
-                    {
-                        //if (grid->getSparseIndex(index) == INVALID_INDEX) continue;
-
-                        if( vertexIndex[level][index] == INVALID_INDEX ) continue;
-
-                        if( vertexIndex[level][index] < startVerticesPerLevel[level] ) continue;
-
-                        xadj.push_back(edgeCounter);
-
-                        real x, y, z;
-                        grid->transIndexToCoords(index, x, y, z);
-
-                        for (const auto dir : DistributionHelper::getDistribution27())
-                        {
-                            const uint neighborIndex = grid->transCoordToIndex(x + dir[0] * grid->getDelta(), 
-                                                                               y + dir[1] * grid->getDelta(), 
-                                                                               z + dir[2] * grid->getDelta());
-
-                            if (neighborIndex == INVALID_INDEX) continue;
-
-                            if (neighborIndex == index) continue;
-
-                            if( vertexIndex[level][neighborIndex] == INVALID_INDEX ) continue;
-
-                            adjncy.push_back( vertexIndex[level][neighborIndex] );
-                            adjwgt.push_back( std::pow(2, level) );
-
-                            edgeCounter++;
-                        }
-
-                        if( grid->getFieldEntry(index) == FLUID_CFC ||
-                            grid->getFieldEntry(index) == FLUID_FCC ||
-                            grid->getFieldEntry(index) == STOPPER_COARSE_UNDER_FINE )
-
-                        {
-                            SPtr<Grid> fineGrid = gridBuilder->getGrid(level + 1);
-
-                            for (const auto dir : DistributionHelper::getDistribution27())
-                            {
-                                if (std::abs(dir[0]) < 0.5 || std::abs(dir[1]) < 0.5 || std::abs(dir[2]) < 0.5) continue;
-
-                                real fineX = x + dir[0] * 0.25 * grid->getDelta();
-                                real fineY = y + dir[1] * 0.25 * grid->getDelta();
-                                real fineZ = z + dir[2] * 0.25 * grid->getDelta();
-
-                                uint childIndex = fineGrid->transCoordToIndex(fineX, fineY, fineZ);
-
-                                if( fineGrid->getFieldEntry(childIndex) == INVALID_INDEX ) continue;
-                                if( vertexIndex[level + 1][childIndex]  == INVALID_INDEX ) continue;
-
-                                for (const auto dir : DistributionHelper::getDistribution27())
-                                {
-                                    const uint neighborIndex = fineGrid->transCoordToIndex( fineX + dir[0] * fineGrid->getDelta(), 
-                                                                                            fineY + dir[1] * fineGrid->getDelta(), 
-                                                                                            fineZ + dir[2] * fineGrid->getDelta() );
-
-                                    if(neighborIndex == INVALID_INDEX) continue;
-
-                                    if (neighborIndex == childIndex) continue;
-
-                                    if( vertexIndex[level + 1][neighborIndex] == INVALID_INDEX ) continue;
-
-                                    adjncy.push_back( vertexIndex[level + 1][neighborIndex] );
-                                    adjwgt.push_back( std::pow(2, level) );
-
-                                    edgeCounter++;
-                                }
-                            }
-                        }
-                    }
-                }
-
-                xadj.push_back( edgeCounter );
-
-                std::cout << "Checkpoint 3:" << std::endl;
-                
-                idx_t nWeights  = 1;
-                idx_t nParts    = 4;
-                idx_t objval    = 0;
-
-                std::vector<idx_t> part( vertexCounter );
-                
-                std::cout << vertexCounter << std::endl;
-                std::cout << edgeCounter << std::endl;
-                std::cout << xadj.size()  << std::endl;
-                std::cout << adjncy.size() << std::endl;
-
-                //int ret = METIS_PartGraphRecursive(&vertexCounter, &nWeights, xadj.data(), adjncy.data(),
-                // 				                   vwgt.data(), NULL, adjwgt.data(), &nParts, 
-                //                                   NULL, NULL, NULL, &objval, part.data());
-
-                int ret = METIS_PartGraphKway(&vertexCounter, &nWeights, xadj.data(), adjncy.data(),
-                 				              vwgt.data(), NULL, NULL/*adjwgt.data()*/, &nParts, 
-                                              NULL, NULL, NULL, &objval, part.data());
-
-                std::cout << "objval:" << objval << std::endl;
-
-                std::cout << "Checkpoint 4:" << std::endl;
-
-                //uint partCounter = 0;
-                
-                for( uint level = 0; level < gridBuilder->getNumberOfLevels(); level++ )
-                {
-                    SPtr<Grid> grid = gridBuilder->getGrid( level );
-
-                    for (uint index = 0; index < grid->getSize(); index++)
-                    {
-                        if (grid->getSparseIndex(index) == INVALID_INDEX) continue;
-
-                        grid->setFieldEntry(index, part[vertexIndex[level][index]]);
-
-                        //partCounter++;
-                    }
-                }
-
-                std::cout << "Checkpoint 5:" << std::endl;
-
-                gridBuilder->writeGridsToVtk("F:/Work/Computations/gridGenerator/grid/Partition_");
-
-            }
-
-            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-            
-            {
-
-                for( int level = gridBuilder->getNumberOfLevels()-1; level >= 0 ; level-- )
-                {
-                    std::vector< std::vector<idx_t> > vertexIndex( gridBuilder->getNumberOfLevels() );
-
-                    std::vector<idx_t> xadj;
-                    std::vector<idx_t> adjncy;
-
-                    std::vector<idx_t> vwgt;
-                    std::vector<idx_t> adjwgt;
-
-                    idx_t vertexCounter = 0;
-                    uint edgeCounter = 0;
-
-                    SPtr<Grid> grid = gridBuilder->getGrid( level );
-
-                    vertexIndex[level].resize( grid->getSize() );
-
-                    for (uint index = 0; index < grid->getSize(); index++)
-                    {
-                        if (grid->getSparseIndex(index) == INVALID_INDEX)
-                        {
-                            vertexIndex[level][index] = INVALID_INDEX;
-                            continue;
-                        }
-
-                        vertexIndex[level][index] = vertexCounter;
-
-                        vwgt.push_back( std::pow(2, level) );
-                        //vwgt.push_back( std::pow(2, 2*level) );
-                        vertexCounter++;
-                    }
-
-                    for (uint index = 0; index < grid->getSize(); index++)
-                    {
-                        //if (grid->getSparseIndex(index) == INVALID_INDEX) continue;
-
-                        if( vertexIndex[level][index] == INVALID_INDEX ) continue;
-
-                        xadj.push_back(edgeCounter);
-
-                        real x, y, z;
-                        grid->transIndexToCoords(index, x, y, z);
-
-                        for (const auto dir : DistributionHelper::getDistribution27())
-                        {
-                            const uint neighborIndex = grid->transCoordToIndex(x + dir[0] * grid->getDelta(), 
-                                                                               y + dir[1] * grid->getDelta(), 
-                                                                               z + dir[2] * grid->getDelta());
-
-                            if (neighborIndex == INVALID_INDEX) continue;
-
-                            if (neighborIndex == index) continue;
-
-                            if( vertexIndex[level][neighborIndex] == INVALID_INDEX ) continue;
-
-                            adjncy.push_back( vertexIndex[level][neighborIndex] );
-                            adjwgt.push_back( std::pow(2, level) );
-
-                            edgeCounter++;
-                        }
-                    }
-
-                    xadj.push_back( edgeCounter );
-
-                    std::cout << "Checkpoint 3:" << std::endl;
-                
-                    idx_t nWeights  = 1;
-                    idx_t nParts    = 4;
-                    idx_t objval    = 0;
-
-                    std::vector<idx_t> part( vertexCounter );
-                
-                    std::cout << vertexCounter << std::endl;
-                    std::cout << edgeCounter << std::endl;
-                    std::cout << xadj.size()  << std::endl;
-                    std::cout << adjncy.size() << std::endl;
-
-                    int ret = METIS_PartGraphRecursive(&vertexCounter, &nWeights, xadj.data(), adjncy.data(),
-                     				                   NULL/*vwgt.data()*/, NULL, NULL/*adjwgt.data()*/, &nParts, 
-                                                       NULL, NULL, NULL, &objval, part.data());
-
-                    //int ret = METIS_PartGraphKway(&vertexCounter, &nWeights, xadj.data(), adjncy.data(),
-                 			//	                  NULL/*vwgt.data()*/, NULL, NULL/*adjwgt.data()*/, &nParts, 
-                    //                              NULL, NULL, NULL, &objval, part.data());
-
-                    std::cout << "objval:" << objval << std::endl;
-
-                    std::cout << "Checkpoint 4:" << std::endl;
-
-                    for (uint index = 0; index < grid->getSize(); index++)
-                    {
-                        if (vertexIndex[level][index] == INVALID_INDEX) continue;
-
-                        if( grid->getFieldEntry(index) == FLUID_CFC ||
-                            grid->getFieldEntry(index) == FLUID_FCC ||
-                            grid->getFieldEntry(index) == STOPPER_COARSE_UNDER_FINE )
-                        {
-                            SPtr<Grid> fineGrid = gridBuilder->getGrid(level+1);
-                            
-                            real x, y, z;
-                            grid->transIndexToCoords(index, x, y, z);
-
-                            for (const auto dir : DistributionHelper::getDistribution27())
-                            {
-                                if (std::abs(dir[0]) < 0.5 || std::abs(dir[1]) < 0.5 || std::abs(dir[2]) < 0.5) continue;
-
-                                real fineX = x + dir[0] * 0.25 * grid->getDelta();
-                                real fineY = y + dir[1] * 0.25 * grid->getDelta();
-                                real fineZ = z + dir[2] * 0.25 * grid->getDelta();
-
-                                uint childIndex = fineGrid->transCoordToIndex(fineX, fineY, fineZ);
-
-                                if( childIndex == INVALID_INDEX ) continue;
+    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-                                fineGrid->setFieldEntry(childIndex, part[vertexIndex[level][index]]);
-                                //fineGrid->setFieldEntry(childIndex, grid->getFieldEntry(index));
-                            }
-                        }
+    GksMeshAdapter meshAdapter;
 
-                        grid->setFieldEntry(index, part[vertexIndex[level][index]]);
-                    }
-                }
+    meshAdapter.inputGrid( gridBuilder );
 
-                gridBuilder->writeGridsToVtk("F:/Work/Computations/gridGenerator/grid/Partition_");
+    meshAdapter.findQuadtreeConnectivity( gridBuilder );
 
-            }
+    meshAdapter.findCellToCellConnectivity( gridBuilder );
 
-            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    meshAdapter.countCells();
 
-            return;
+    meshAdapter.partitionCells();
 
-            gridGenerator = GridGenerator::make(gridBuilder, para);
-        }
-    }
-    else
-    {
-        gridGenerator = GridReader::make(FileFormat::BINARY, para);
-        //gridGenerator = GridReader::make(FileFormat::ASCII, para);
-    }
+    meshAdapter.generateNodes( gridBuilder );
 
-    logFile.close();
+    meshAdapter.computeCellGeometry();
 
-    //return;
-
-    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+    meshAdapter.generateFaces( gridBuilder );
 
+    meshAdapter.sortFaces();
 
-    std::ifstream stream;
-    stream.open(configPath.c_str(), std::ios::in);
-    if (stream.fail())
-        throw std::runtime_error("can not open config file!");
+    meshAdapter.countFaces();
 
-    UPtr<input::Input> input = input::Input::makeInput(stream, "config");
+    meshAdapter.generateInterfaceConnectivity();
 
-    setParameters(para, input);
+    meshAdapter.writeMeshVTK( "F:/Work/Computations/gridGenerator/grid/Mesh.vtk" );
 
-    Simulation sim;
-    SPtr<FileWriter> fileWriter = SPtr<FileWriter>(new FileWriter());
-    sim.init(para, gridGenerator, fileWriter);
-    sim.run();
+    meshAdapter.writeMeshFaceVTK( "F:/Work/Computations/gridGenerator/grid/MeshFaces.vtk" );
 }
 
-
 int main( int argc, char* argv[])
 {
-     MPI_Init(&argc, &argv);
-    std::string str, str2; 
-    if ( argv != NULL )
-    {
-        str = static_cast<std::string>(argv[0]);
-        if (argc > 1)
-        {
-            str2 = static_cast<std::string>(argv[1]);
-            try
-            {
-                multipleLevel(str2);
-            }
-            catch (const std::exception& e)
-            {
-                *logging::out << logging::Logger::ERROR << e.what() << "\n";
-                //MPI_Abort(MPI_COMM_WORLD, -1);
-            }
-            catch (...)
-            {
-                std::cout << "unknown exeption" << std::endl;
-            }
-        }
-        else
-        {
-            try
-            {
-                multipleLevel("F:/Work/Computations/gridGenerator/inp/configTest.txt");
-            }
-            catch (const std::exception& e)
-            {
-                
-                *logging::out << logging::Logger::ERROR << e.what() << "\n";
-                //std::cout << e.what() << std::flush;
-                //MPI_Abort(MPI_COMM_WORLD, -1);
-            }
-            catch (const std::bad_alloc e)
-            {
-                
-                *logging::out << logging::Logger::ERROR << "Bad Alloc:" << e.what() << "\n";
-                //std::cout << e.what() << std::flush;
-                //MPI_Abort(MPI_COMM_WORLD, -1);
-            }
-            catch (...)
-            {
-                *logging::out << logging::Logger::ERROR << "Unknown exception!\n";
-                //std::cout << "unknown exeption" << std::endl;
-            }
 
-            std::cout << "\nConfiguration file must be set!: lbmgm <config file>" << std::endl << std::flush;
-            //MPI_Abort(MPI_COMM_WORLD, -1);
-        }
+    logging::Logger::addStream(&std::cout);
+    logging::Logger::setDebugLevel(logging::Logger::Level::INFO_LOW);
+    logging::Logger::timeStamp(logging::Logger::ENABLE);
+    
+    try
+    {
+        gksTest();
+    }
+    catch (const std::exception& e)
+    {     
+        *logging::out << logging::Logger::ERROR << e.what() << "\n";
+    }
+    catch (const std::bad_alloc& e)
+    {  
+        *logging::out << logging::Logger::ERROR << "Bad Alloc:" << e.what() << "\n";
+    }
+    catch (...)
+    {
+        *logging::out << logging::Logger::ERROR << "Unknown exception!\n";
     }
 
-
-   /*
-   MPE_Init_log() & MPE_Finish_log() are NOT needed when
-   liblmpe.a is linked with this program.  In that case,
-   MPI_Init() would have called MPE_Init_log() already.
-   */
-#if defined( MPI_LOGGING )
-   MPE_Init_log();
-#endif
-
-#if defined( MPI_LOGGING )
-   if ( argv != NULL )
-      MPE_Finish_log( argv[0] );
-   if ( str != "" )
-      MPE_Finish_log( str.c_str() );
-   else
-      MPE_Finish_log( "TestLog" );
-#endif
-
-   MPI_Finalize();
    return 0;
 }
diff --git a/targets/libs/GksMeshAdapter/3rdPartyLinking.cmake b/targets/libs/GksMeshAdapter/3rdPartyLinking.cmake
new file mode 100644
index 000000000..6feb9029e
--- /dev/null
+++ b/targets/libs/GksMeshAdapter/3rdPartyLinking.cmake
@@ -0,0 +1,6 @@
+include (${CMAKE_SOURCE_DIR}/${cmakeMacroPath}/Cuda/Link.cmake)
+linkCuda(${targetName})
+include (${CMAKE_SOURCE_DIR}/${cmakeMacroPath}/MPI/Link.cmake)
+linkMPI(${targetName})
+include (${CMAKE_SOURCE_DIR}/${cmakeMacroPath}/Boost/Link.cmake)
+linkBoost(${targetName} "serialization")
\ No newline at end of file
diff --git a/targets/libs/GksMeshAdapter/CMakeLists.txt b/targets/libs/GksMeshAdapter/CMakeLists.txt
new file mode 100644
index 000000000..fadfa8657
--- /dev/null
+++ b/targets/libs/GksMeshAdapter/CMakeLists.txt
@@ -0,0 +1,18 @@
+setTargetNameToFolderName(${CMAKE_CURRENT_LIST_DIR}) 
+
+set(linkDirectories "")
+set(libsToLink GridGenerator Core)
+
+set(includeDirectories ${CMAKE_SOURCE_DIR}/src/${targetName}
+                       ${CMAKE_SOURCE_DIR}/src
+                       ${CMAKE_SOURCE_DIR}/src/GridGenerator
+                       ${CMAKE_SOURCE_DIR}/src/Core )
+
+#glob files and save in MY_SRCS
+include(CMakePackage.cmake)
+
+buildLib(${targetName} "${MY_SRCS}" "${linkDirectories}" "${libsToLink}" "${includeDirectories}")
+groupTarget(${targetName} ${gksLibraryFolder})
+
+#Specify the linking to 3rdParty libs
+include(3rdPartyLinking.cmake)
diff --git a/targets/libs/GksMeshAdapter/CMakePackage.cmake b/targets/libs/GksMeshAdapter/CMakePackage.cmake
new file mode 100644
index 000000000..7ec316fe0
--- /dev/null
+++ b/targets/libs/GksMeshAdapter/CMakePackage.cmake
@@ -0,0 +1,8 @@
+#FILE ENDINGS
+resetFileEndingsToCollect()
+addCAndCPPFileTypes()
+
+#GLOB SOURCE FILES IN MY_SRCS
+unset(MY_SRCS)
+includeRecursiveAllFilesFrom(${targetName} ${CMAKE_CURRENT_LIST_DIR})
+includeRecursiveProductionFilesFrom(${targetName} ${CMAKE_SOURCE_DIR}/src/${targetName})
\ No newline at end of file
-- 
GitLab